Skip to content

ParseLiveListElementSnapshot added #329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9a2ce35
Created ParseLiveList
fischerscode Mar 5, 2020
442b188
LiveList & LivListBuilder works
fischerscode Mar 7, 2020
3ab5121
Cleanup
fischerscode Mar 7, 2020
567316e
changed to animated list
fischerscode Mar 7, 2020
aba2003
Fix in dataloading
fischerscode Mar 8, 2020
35f4d21
updated AnimatedList
fischerscode Mar 8, 2020
a28fee3
Finished Animations & cleanup
fischerscode Mar 9, 2020
7289131
handle reconnect
fischerscode Mar 9, 2020
05bc1c0
Added dispose methodes & renamed classes & cleanup
fischerscode Mar 9, 2020
ddd1bc0
cleanup
fischerscode Mar 9, 2020
846775c
Fix animation duration
fischerscode Mar 9, 2020
78883ab
added README ParseLiveList section
fischerscode Mar 9, 2020
c427b46
Initialized example_livelist
fischerscode Mar 9, 2020
8fb56fd
Update application_constants.dart
fischerscode Mar 9, 2020
4d8982d
Update .gitignore
fischerscode Mar 9, 2020
43da921
Revert "Update .gitignore"
fischerscode Mar 9, 2020
a2b4ff3
Update .gitignore
fischerscode Mar 9, 2020
10613b1
HotFix: object Update from client
fischerscode Mar 9, 2020
40edcc1
Implemented simple example
fischerscode Mar 9, 2020
769cb3d
Update README.md
fischerscode Mar 9, 2020
2642cd4
Update main.dart
fischerscode Mar 9, 2020
a5e497c
Update README.md
fischerscode Mar 9, 2020
ef27472
Update README.md
fischerscode Mar 9, 2020
1ecc000
LiveList - Performance Improvement
fischerscode Mar 10, 2020
5d0b3cb
LiveList - Performance Improvement
fischerscode Mar 10, 2020
b534355
Merge branch 'live-list' of https://github.com/maaeps/Parse-SDK-Flutt…
fischerscode Mar 10, 2020
b0b06ff
example_livelist: use clientKey
fischerscode Mar 10, 2020
741cf40
Changed example_livelist query
fischerscode Mar 10, 2020
da675da
Remove: RemovedItemBuilder
fischerscode Mar 10, 2020
04a49c7
removed firstBuild
fischerscode Mar 10, 2020
9e25813
ParseLiveListElementSnapshot added
fischerscode Mar 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example_livelist/lib/application_constants.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const String keyApplicationName = '';
const String keyParseApplicationId = '';
const String keyParseMasterKey = '';
const String keyParseClientKey = '';
const String keyParseServerUrl = '';
const String keyParseLiveServerUrl = '';
const bool keyDebug = true;
20 changes: 11 additions & 9 deletions example_livelist/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class _MyAppState extends State<MyApp> {
initFailed = !success;
if (success)
_queryBuilder = QueryBuilder<ParseObject>(ParseObject('Test'))
..orderByAscending('order');
;
..orderByAscending('order')
..whereNotEqualTo('show', false);
});
}).catchError((dynamic _) {
setState(() {
Expand Down Expand Up @@ -80,31 +80,32 @@ class _MyAppState extends State<MyApp> {
child: ParseLiveListWidget<ParseObject>(
query: _queryBuilder,
duration: const Duration(seconds: 1),
childBuilder:
(BuildContext context, bool failed, ParseObject loadedData) {
if (failed) {
childBuilder: (BuildContext context,
ParseLiveListElementSnapshot<ParseObject> snapshot) {
if (snapshot.failed) {
return const Text('something went wrong!');
} else if (loadedData != null) {
} else if (snapshot.hasData) {
return ListTile(
title: Row(
children: <Widget>[
Flexible(
child: Text(loadedData.get<int>('order').toString()),
child: Text(
snapshot.loadedData.get<int>('order').toString()),
flex: 1,
),
Flexible(
child: Container(
alignment: Alignment.center,
child: Text(
loadedData.get<String>('text'),
snapshot.loadedData.get<String>('text'),
),
),
flex: 10,
),
],
),
onLongPress: () {
objectFormKey.currentState.setObject(loadedData);
objectFormKey.currentState.setObject(snapshot.loadedData);
},
);
} else {
Expand Down Expand Up @@ -179,6 +180,7 @@ class _ObjectFormState extends State<ObjectForm> {
setState(() {
_formKey.currentState.save();
final ParseObject object = _currentObject;
//Delay to highlight the animation.
Future<void>.delayed(const Duration(seconds: 1))
.then((_) {
object.save();
Expand Down
105 changes: 65 additions & 40 deletions lib/src/utils/parse_live_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,27 +160,28 @@ class ParseLiveList<T extends ParseObject> {
for (int i = 0; i < _list.length; i++) {
if (after(object, _list[i].object) != true) {
_list.insert(i, ParseLiveListElement<T>(object, loaded: loaded));
_eventStreamController.sink.add(ParseLiveListAddEvent<T>(i, object));
_eventStreamController.sink.add(ParseLiveListAddEvent<T>(
i, object?.clone(object?.toJson(full: true))));
return;
}
}
_list.add(ParseLiveListElement<T>(object, loaded: loaded));
_eventStreamController.sink
.add(ParseLiveListAddEvent<T>(_list.length - 1, object));
_eventStreamController.sink.add(ParseLiveListAddEvent<T>(
_list.length - 1, object?.clone(object?.toJson(full: true))));
}

void _objectUpdated(T object) {
for (int i = 0; i < _list.length; i++) {
if (_list[i].object.get<String>(keyVarObjectId) ==
object.get<String>(keyVarObjectId)) {
//TODO: better soulution
// if (after(_list[i].object, object) == null) {
// _list[i].object = object;
// } else {
_list.removeAt(i).dispose();
_eventStreamController.sink.add(ParseLiveListDeleteEvent<T>(i, object));
_objectAdded(object);
// }
if (after(_list[i].object, object) == null) {
_list[i].object = object;
} else {
_list.removeAt(i).dispose();
_eventStreamController.sink.add(ParseLiveListDeleteEvent<T>(
i, object?.clone(object?.toJson(full: true))));
_objectAdded(object);
}
break;
}
}
Expand All @@ -191,7 +192,8 @@ class ParseLiveList<T extends ParseObject> {
if (_list[i].object.get<String>(keyVarObjectId) ==
object.get<String>(keyVarObjectId)) {
_list.removeAt(i).dispose();
_eventStreamController.sink.add(ParseLiveListDeleteEvent<T>(i, object));
_eventStreamController.sink.add(ParseLiveListDeleteEvent<T>(
i, object?.clone(object?.toJson(full: true))));
break;
}
}
Expand All @@ -205,9 +207,10 @@ class ParseLiveList<T extends ParseObject> {
keyVarObjectId, _list[index].object.get<String>(keyVarObjectId))
..setLimit(1);
final ParseResponse response = await queryBuilder.query();
if (response.success) {
if (response.success && response.results != null) {
_list[index].object = response.results.first;
} else {
_list[index].object = null;
throw response.error;
}
}
Expand Down Expand Up @@ -256,12 +259,12 @@ class ParseLiveListElement<T extends ParseObject> {

Stream<T> get stream => _streamController?.stream;

T get object => _object;
T get object => _object?.clone(_object?.toJson(full: true));

set object(T value) {
_loaded = true;
_object = value;
_streamController?.add(object);
_streamController?.add(_object?.clone(_object?.toJson(full: true)));
}

bool get loaded => _loaded;
Expand Down Expand Up @@ -291,12 +294,20 @@ class ParseLiveListDeleteEvent<T extends ParseObject>
ParseLiveListDeleteEvent(int index, T object) : super(index, object);
}

typedef Stream<T> StreamGetter<T extends ParseObject>();
typedef T DataGetter<T extends ParseObject>();
typedef Widget ChildBuilder<T extends ParseObject>(
BuildContext context, bool failed, T loadedData);
typedef Widget RemovedItemBuilder<T extends ParseObject>(
BuildContext context, int index, T oldObject);
typedef StreamGetter<T extends ParseObject> = Stream<T> Function();
typedef DataGetter<T extends ParseObject> = T Function();
typedef ChildBuilder<T extends ParseObject> = Widget Function(
BuildContext context, ParseLiveListElementSnapshot<T> snapshot);

class ParseLiveListElementSnapshot<T extends ParseObject> {
ParseLiveListElementSnapshot({this.loadedData, this.error});

final T loadedData;
final ParseError error;

bool get hasData => loadedData != null;
bool get failed => error != null;
}

class ParseLiveListWidget<T extends ParseObject> extends StatefulWidget {
const ParseLiveListWidget(
Expand Down Expand Up @@ -327,8 +338,8 @@ class ParseLiveListWidget<T extends ParseObject> extends StatefulWidget {
final bool reverse;
final bool shrinkWrap;

final ChildBuilder childBuilder;
final RemovedItemBuilder<T> removedItemBuilder;
final ChildBuilder<T> childBuilder;
final ChildBuilder<T> removedItemBuilder;

@override
_ParseLiveListWidgetState<T> createState() =>
Expand Down Expand Up @@ -390,7 +401,7 @@ class _ParseLiveListWidgetState<T extends ParseObject>
ParseLiveList<T> _liveList;
final GlobalKey<AnimatedListState> _animatedListKey =
GlobalKey<AnimatedListState>();
final RemovedItemBuilder<T> removedItemBuilder;
final ChildBuilder<T> removedItemBuilder;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -446,7 +457,7 @@ class ParseLiveListElementWidget<T extends ParseObject> extends StatefulWidget {
final DataGetter<T> loadedData;
final Animation<double> sizeFactor;
final Duration duration;
final ChildBuilder childBuilder;
final ChildBuilder<T> childBuilder;

@override
_ParseLiveListElementWidgetState<T> createState() {
Expand All @@ -459,23 +470,38 @@ class _ParseLiveListElementWidgetState<T extends ParseObject>
with SingleTickerProviderStateMixin {
_ParseLiveListElementWidgetState(
DataGetter<T> loadedDataGetter, StreamGetter<T> stream) {
loadedData = loadedDataGetter();
// loadedData = loadedDataGetter();
_snapshot = ParseLiveListElementSnapshot<T>(loadedData: loadedDataGetter());
if (stream != null) {
_streamSubscription = stream().listen((T data) {
if (widget != null) {
setState(() {
loadedData = data;
});
} else {
loadedData = data;
}
});
_streamSubscription = stream().listen(
(T data) {
if (widget != null) {
setState(() {
_snapshot = ParseLiveListElementSnapshot<T>(loadedData: data);
});
} else {
_snapshot = ParseLiveListElementSnapshot<T>(loadedData: data);
}
},
onError: (Object error) {
if (error is ParseError) {
if (widget != null) {
setState(() {
_snapshot = ParseLiveListElementSnapshot<T>(error: error);
});
} else {
_snapshot = ParseLiveListElementSnapshot<T>(error: error);
}
}
},
cancelOnError: false,
);
}
}
T loadedData;
bool failed = false;

ParseLiveListElementSnapshot<T> _snapshot;

StreamSubscription<T> _streamSubscription;
bool firstBuild = true;

@override
void dispose() {
Expand All @@ -491,10 +517,9 @@ class _ParseLiveListElementWidgetState<T extends ParseObject>
child: AnimatedSize(
duration: widget.duration,
vsync: this,
child: widget.childBuilder(context, failed, loadedData),
child: widget.childBuilder(context, _snapshot),
),
);
firstBuild = false;
return result;
}
}