Skip to content

Commit 8febea6

Browse files
committed
moar fixes, on watcher tests
1 parent d37bf51 commit 8febea6

File tree

12 files changed

+233
-179
lines changed

12 files changed

+233
-179
lines changed

lib/flutter_data.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ part 'src/storage/in_memory_local_storage.dart';
4343
part 'src/utils/data_state.dart';
4444
part 'src/utils/extensions.dart';
4545
part 'src/utils/framework.dart';
46-
part 'src/utils/offline.dart';
46+
part 'src/utils/offline_operations.dart';

lib/src/adapter/adapter.dart

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
5050
bool _stopInitialization = false;
5151

5252
// None of these fields below can be late finals as they might be re-initialized
53-
bool? _remote;
5453
Ref? _ref;
5554

5655
/// All adapters for the relationship subgraph of [T] and their relationships.
@@ -374,6 +373,13 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
374373
return model;
375374
}
376375

376+
Set<String> _edgesFor(String fromKey, String name) {
377+
final result = db.select(
378+
'SELECT src, dest FROM _edges WHERE (src = ? AND name = ?) OR (dest = ? AND inverse = ?)',
379+
[fromKey, name, fromKey, name]);
380+
return {for (final r in result) r['dest']};
381+
}
382+
377383
void _initializeRelationships(T model, {String? fromKey}) {
378384
final metadatas = relationshipMetas.values;
379385
for (final metadata in metadatas) {
@@ -382,11 +388,7 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
382388
// if rel was omitted, fill with info of previous key
383389
// TODO optimize: put outside loop and query edgesFor just once
384390
if (fromKey != null && relationship._uninitializedKeys == null) {
385-
// TODO DRY!
386-
final result = db.select(
387-
'SELECT src, dest FROM _edges WHERE (src = ? AND name = ?) OR (dest = ? AND inverse = ?)',
388-
[fromKey, metadata.name, fromKey, metadata.name]);
389-
relationship._uninitializedKeys = {for (final r in result) r['dest']};
391+
relationship._uninitializedKeys = _edgesFor(fromKey, metadata.name);
390392
}
391393
relationship.initialize(
392394
ownerKey: model._key!,
@@ -441,28 +443,3 @@ abstract class _BaseAdapter<T extends DataModelMixin<T>> with _Lifecycle {
441443
return map;
442444
}
443445
}
444-
445-
/// Annotation on a [DataModelMixin] model to request an [Adapter] be generated for it.
446-
///
447-
/// Takes a list of [adapters] to be mixed into this [Adapter].
448-
/// Public methods of these [adapters] mixins will be made available in the adapter
449-
/// via extensions.
450-
///
451-
/// A classic example is:
452-
///
453-
/// ```
454-
/// @JsonSerializable()
455-
/// @DataAdapter([JSONAPIAdapter])
456-
/// class Todo with DataModel<Todo> {
457-
/// @override
458-
/// final int id;
459-
/// final String title;
460-
/// final bool completed;
461-
///
462-
/// Todo({this.id, this.title, this.completed = false});
463-
/// }
464-
///```
465-
class DataAdapter {
466-
final List<Type> adapters;
467-
const DataAdapter(this.adapters);
468-
}

lib/src/adapter/remote_adapter.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,15 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
5151
///
5252
/// See also: [urlForFindAll], [methodForFindAll].
5353
Future<List<T>> findAll({
54-
bool? remote,
55-
bool? background,
54+
bool remote = true,
55+
bool background = false,
5656
Map<String, dynamic>? params,
5757
Map<String, String>? headers,
58-
bool? syncLocal,
58+
bool syncLocal = false,
5959
OnSuccessAll<T>? onSuccess,
6060
OnErrorAll<T>? onError,
6161
DataRequestLabel? label,
6262
}) async {
63-
remote ??= _remote ?? true;
64-
background ??= false;
65-
syncLocal ??= false;
6663
params = await defaultParams & params;
6764
headers = await defaultHeaders & headers;
6865

@@ -85,7 +82,7 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
8582
headers: headers,
8683
label: label,
8784
onSuccess: (data, label) async {
88-
if (syncLocal!) {
85+
if (syncLocal) {
8986
clearLocal();
9087
}
9188
onSuccess ??= (data, label, _) async {
@@ -395,7 +392,7 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
395392
if (response != null) {
396393
contentType = response.headers['content-type'] ?? 'application/json';
397394

398-
responseBody = await Isolate.run(() {
395+
responseBody = () {
399396
if (returnBytes) {
400397
return response!.bodyBytes;
401398
} else if (response!.body.isNotEmpty) {
@@ -407,7 +404,7 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
407404
}
408405
}
409406
return null;
410-
});
407+
}();
411408
}
412409
} on FormatException catch (e, stack) {
413410
error = e;
@@ -501,6 +498,7 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
501498
return label.model as R?;
502499
}
503500

501+
print('1');
504502
final data = await deserializeAsync(body as Map<String, dynamic>,
505503
key: label.model!._key);
506504
final model = data.model!;
@@ -509,6 +507,7 @@ mixin _RemoteAdapter<T extends DataModelMixin<T>> on _SerializationAdapter<T> {
509507
if (model._key != label.model!._key) {
510508
deleteLocalByKeys({label.model!._key!});
511509
}
510+
print('2');
512511
model.saveLocal();
513512

514513
log(label, 'saved in local storage and remote');

lib/src/adapter/watch_adapter.dart

Lines changed: 42 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
1111
/// ref.books.watchAll();
1212
/// ```
1313
DataState<List<T>> watchAll({
14-
bool? remote,
14+
bool remote = false,
1515
Map<String, dynamic>? params,
1616
Map<String, String>? headers,
17-
bool? syncLocal,
17+
bool syncLocal = false,
1818
String? finder,
1919
DataRequestLabel? label,
2020
}) {
@@ -42,7 +42,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
4242
/// ```
4343
DataState<T?> watchOne(
4444
Object model, {
45-
bool? remote,
45+
bool remote = false,
4646
Map<String, dynamic>? params,
4747
Map<String, String>? headers,
4848
AlsoWatch<T>? alsoWatch,
@@ -64,10 +64,10 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
6464
// notifiers
6565

6666
DataStateNotifier<List<T>> watchAllNotifier(
67-
{bool? remote,
67+
{bool remote = false,
6868
Map<String, dynamic>? params,
6969
Map<String, String>? headers,
70-
bool? syncLocal,
70+
bool syncLocal = false,
7171
String? finder,
7272
DataRequestLabel? label}) {
7373
final provider = watchAllProvider(
@@ -82,7 +82,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
8282
}
8383

8484
DataStateNotifier<T?> watchOneNotifier(Object model,
85-
{bool? remote,
85+
{bool remote = false,
8686
Map<String, dynamic>? params,
8787
Map<String, String>? headers,
8888
AlsoWatch<T>? alsoWatch,
@@ -103,16 +103,13 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
103103

104104
@protected
105105
DataStateNotifier<List<T>> _watchAllNotifier({
106-
bool? remote,
106+
bool remote = false,
107107
Map<String, dynamic>? params,
108108
Map<String, String>? headers,
109-
bool? syncLocal,
109+
bool syncLocal = false,
110110
String? finder,
111111
DataRequestLabel? label,
112112
}) {
113-
remote ??= _remote;
114-
syncLocal ??= false;
115-
116113
final maybeFinder = _internalHolder?.finders[finder]?.call(this);
117114
final finderFn = maybeFinder is DataFinderAll<T> ? maybeFinder : findAll;
118115

@@ -128,15 +125,15 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
128125
}
129126

130127
final notifier = DataStateNotifier<List<T>>(
131-
data: DataState(_getUpdatedModels(), isLoading: remote!),
128+
data: DataState(_getUpdatedModels(), isLoading: remote),
132129
);
133130

134131
notifier._reloadFn = () async {
135132
if (!notifier.mounted) {
136133
return;
137134
}
138135

139-
if (remote!) {
136+
if (remote) {
140137
notifier.updateWith(isLoading: true);
141138
}
142139

@@ -146,6 +143,11 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
146143
headers: headers,
147144
syncLocal: syncLocal,
148145
label: label,
146+
// onSuccess: (response, label, _) async {
147+
// response;
148+
// print('got $response');
149+
// return [];
150+
// },
149151
onError: (e, label, _) async {
150152
try {
151153
await onError<List<T>>(e, label);
@@ -221,7 +223,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
221223
@protected
222224
DataStateNotifier<T?> _watchOneNotifier(
223225
String key, {
224-
bool? remote,
226+
bool remote = false,
225227
Map<String, dynamic>? params,
226228
Map<String, String>? headers,
227229
AlsoWatch<T>? alsoWatch,
@@ -230,7 +232,6 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
230232
}) {
231233
final id = core.getIdForKey(key);
232234

233-
remote ??= _remote;
234235
final maybeFinder = _internalHolder?.finders[finder]?.call(this);
235236
final finderFn = maybeFinder is DataFinderOne<T> ? maybeFinder : findOne;
236237

@@ -243,33 +244,30 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
243244

244245
// closure to get latest model and watchable relationship pairs
245246
T? _getUpdatedModel() {
246-
// return localAdapter.storage.readTxn(() {
247-
// final model = findOneLocal(key);
248-
// if (model != null) {
249-
// // get all metas provided via `alsoWatch`
250-
// final metas = alsoWatch
251-
// ?.call(RelationshipGraphNode<T>())
252-
// .whereType<RelationshipMeta>();
253-
254-
// // recursively get applicable watch key pairs for each meta -
255-
// // from top to bottom (e.g. `p`, `p.familia`, `p.familia.cottage`)
256-
// alsoWatchPairs = {
257-
// ...?metas
258-
// ?.map((meta) => _getPairsForMeta(meta._top, model._key!))
259-
// .nonNulls
260-
// .expand((_) => _)
261-
// };
262-
// } else {
263-
// // if there is no model nothing should be watched, reset pairs
264-
// alsoWatchPairs = {};
265-
// }
266-
// return model;
267-
// });
268-
// TODO restore
247+
final model = findOneLocal(key);
248+
if (model != null) {
249+
// get all metas provided via `alsoWatch`
250+
final metas = alsoWatch
251+
?.call(RelationshipGraphNode<T>())
252+
.whereType<RelationshipMeta>();
253+
254+
// recursively get applicable watch key pairs for each meta -
255+
// from top to bottom (e.g. `p`, `p.familia`, `p.familia.cottage`)
256+
alsoWatchPairs = {
257+
...?metas
258+
?.map((meta) => _getPairsForMeta(meta._top, model._key!))
259+
.nonNulls
260+
.expand((_) => _)
261+
};
262+
} else {
263+
// if there is no model nothing should be watched, reset pairs
264+
alsoWatchPairs = {};
265+
}
266+
return model;
269267
}
270268

271269
final notifier = DataStateNotifier<T?>(
272-
data: DataState(_getUpdatedModel(), isLoading: remote!),
270+
data: DataState(_getUpdatedModel(), isLoading: remote),
273271
);
274272

275273
final alsoWatchNames = alsoWatch
@@ -283,7 +281,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
283281
notifier._reloadFn = () async {
284282
if (!notifier.mounted || id == null) return;
285283

286-
if (remote!) {
284+
if (remote) {
287285
notifier.updateWith(isLoading: true);
288286
}
289287

@@ -442,11 +440,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
442440
if (meta == null) return {};
443441
print('--- [read] _getPairsForMeta');
444442

445-
// TODO restore
446-
final edges = []; // storage.edgesFor([(ownerKey, meta.name)]);
447-
final relationshipKeys = {
448-
for (final e in edges) e.from == ownerKey ? e.to : e.from
449-
};
443+
final relationshipKeys = _edgesFor(ownerKey, meta.name);
450444

451445
return {
452446
// include key pairs of (owner, key)
@@ -462,14 +456,13 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
462456

463457
AutoDisposeStateNotifierProvider<DataStateNotifier<List<T>>,
464458
DataState<List<T>>> watchAllProvider({
465-
bool? remote,
459+
bool remote = false,
466460
Map<String, dynamic>? params,
467461
Map<String, String>? headers,
468-
bool? syncLocal,
462+
bool syncLocal = false,
469463
String? finder,
470464
DataRequestLabel? label,
471465
}) {
472-
remote ??= _remote;
473466
return _watchAllProvider(
474467
WatchArgs(
475468
remote: remote,
@@ -498,7 +491,7 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
498491
AutoDisposeStateNotifierProvider<DataStateNotifier<T?>, DataState<T?>>
499492
watchOneProvider(
500493
Object model, {
501-
bool? remote,
494+
bool remote = false,
502495
Map<String, dynamic>? params,
503496
Map<String, String>? headers,
504497
AlsoWatch<T>? alsoWatch,
@@ -507,7 +500,6 @@ mixin _WatchAdapter<T extends DataModelMixin<T>> on _RemoteAdapter<T> {
507500
}) {
508501
final key = core.getKeyForModelOrId(internalType, model);
509502

510-
remote ??= _remote;
511503
final relationshipMetas = alsoWatch
512504
?.call(RelationshipGraphNode<T>())
513505
.whereType<RelationshipMeta>()

lib/src/model/relationship/belongs_to.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ class BelongsTo<E extends DataModelMixin<E>> extends Relationship<E, E?> {
4545
if (value == null && newValue != null) {
4646
// addition
4747
super._addAll([newValue]);
48+
return;
4849
}
4950
if (value != null && newValue != null) {
5051
// update
5152
super._update(value!, newValue);
53+
return;
5254
}
5355
if (value != null && newValue == null) {
5456
// removal
5557
super._remove(value!);
58+
return;
5659
}
5760
}
5861

lib/src/model/relationship/relationship.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,22 @@ sealed class Relationship<E extends DataModelMixin<E>, N> with EquatableMixin {
9797
db.execute(
9898
'UPDATE _edges SET dest = ? WHERE src = ? AND name = ? AND dest = ?',
9999
[newValue._key!, ownerKey, name, value._key!]);
100+
_adapter.core._notify(
101+
[ownerKey, newValue._key!],
102+
metadata: _name,
103+
type: DataGraphEventType.updateEdge,
104+
);
100105
return true;
101106
}
102107

103108
bool _remove(E value) {
104109
db.execute('DELETE FROM _edges WHERE src = ? AND name = ? AND dest = ?',
105110
[ownerKey, name, value._key!]);
111+
_adapter.core._notify(
112+
[ownerKey, value._key!],
113+
metadata: _name,
114+
type: DataGraphEventType.removeEdge,
115+
);
106116
return true;
107117
}
108118

0 commit comments

Comments
 (0)