178 lines
4.8 KiB
Dart
178 lines
4.8 KiB
Dart
|
|
import 'dart:async';
|
||
|
|
|
||
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||
|
|
import 'package:faker/faker.dart';
|
||
|
|
import 'package:logging/logging.dart';
|
||
|
|
|
||
|
|
import 'base_model.dart';
|
||
|
|
|
||
|
|
class TestModel extends BaseModel {
|
||
|
|
final log = Logger('TestModel');
|
||
|
|
|
||
|
|
List<Test> tests = [];
|
||
|
|
DocumentSnapshot prev;
|
||
|
|
static const int row_count = 10;
|
||
|
|
bool ended = false;
|
||
|
|
|
||
|
|
StreamSubscription<QuerySnapshot> listener;
|
||
|
|
final Query queryBase = Firestore.instance.collection("/tests");
|
||
|
|
final Query query = Firestore.instance
|
||
|
|
.collection("/tests")
|
||
|
|
// .orderBy("deleted")
|
||
|
|
.orderBy("age", descending: false);
|
||
|
|
|
||
|
|
void initData() async {
|
||
|
|
_clearState();
|
||
|
|
_initListener();
|
||
|
|
load();
|
||
|
|
}
|
||
|
|
|
||
|
|
void _clearState() {
|
||
|
|
prev = null;
|
||
|
|
tests = [];
|
||
|
|
ended = false;
|
||
|
|
if (listener != null) listener.cancel();
|
||
|
|
listener = null;
|
||
|
|
}
|
||
|
|
|
||
|
|
void _initListener() {
|
||
|
|
Query _query = queryBase.orderBy("update_time", descending: true).limit(1);
|
||
|
|
_query.getDocuments(source: Source.server).then((QuerySnapshot snapshot) {
|
||
|
|
int count = snapshot.documents.length;
|
||
|
|
if (count == 1) {
|
||
|
|
var test = Test.fromMap(
|
||
|
|
snapshot.documents[0].data, snapshot.documents[0].documentID);
|
||
|
|
|
||
|
|
Query _queryListener = queryBase
|
||
|
|
.where("update_time", isGreaterThan: test.updateTime)
|
||
|
|
.orderBy("update_time", descending: true);
|
||
|
|
|
||
|
|
listener =
|
||
|
|
_queryListener.snapshots(includeMetadataChanges: true).listen((qs) {
|
||
|
|
qs.documentChanges.forEach((c) {
|
||
|
|
switch (c.type) {
|
||
|
|
case DocumentChangeType.added:
|
||
|
|
var test = Test.fromMap(c.document.data, c.document.documentID);
|
||
|
|
if (tests.contains(test)) {
|
||
|
|
tests[tests.indexOf(test)].name = test.name;
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
if (!tests.contains(test)) {
|
||
|
|
tests.add(test);
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case DocumentChangeType.modified:
|
||
|
|
var test = Test.fromMap(c.document.data, c.document.documentID);
|
||
|
|
if (tests.contains(test)) {
|
||
|
|
bool deleted = c.document.data["deleted"];
|
||
|
|
if (deleted != null && deleted) {
|
||
|
|
tests.remove(test);
|
||
|
|
} else {
|
||
|
|
tests[tests.indexOf(test)].name = test.name;
|
||
|
|
}
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
notifyListeners();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
Future<void> load() async {
|
||
|
|
Query _query = prev != null ? query.startAfterDocument(prev) : query;
|
||
|
|
try {
|
||
|
|
_query
|
||
|
|
// .where("deleted", isNull: null)
|
||
|
|
.limit(row_count)
|
||
|
|
.getDocuments(source: Source.server)
|
||
|
|
.then((QuerySnapshot snapshot) {
|
||
|
|
int count = snapshot.documents.length;
|
||
|
|
ended = count < row_count;
|
||
|
|
prev = count > 0 ? snapshot.documents[count - 1] : prev;
|
||
|
|
snapshot.documents.forEach((e) {
|
||
|
|
var test = Test.fromMap(e.data, e.documentID);
|
||
|
|
if (!tests.contains(test)) tests.add(test);
|
||
|
|
});
|
||
|
|
notifyListeners();
|
||
|
|
});
|
||
|
|
} catch (e) {
|
||
|
|
log.warning("Error!! $e");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void populate() {
|
||
|
|
for (var i = 0; i < 30; i++) {
|
||
|
|
Firestore.instance
|
||
|
|
.collection('tests')
|
||
|
|
.document(faker.person.name())
|
||
|
|
.setData({
|
||
|
|
'name': faker.person.name(),
|
||
|
|
'age': random.decimal(),
|
||
|
|
'update_time': DateTime.now().microsecondsSinceEpoch
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void add() {
|
||
|
|
Firestore.instance
|
||
|
|
.collection('tests')
|
||
|
|
.document(faker.person.name())
|
||
|
|
.setData({
|
||
|
|
'name': faker.person.name(),
|
||
|
|
'age': random.decimal(),
|
||
|
|
'update_time': DateTime.now().microsecondsSinceEpoch
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
void update() {
|
||
|
|
Firestore.instance.collection('tests').document(tests[0].id).setData({
|
||
|
|
'name': faker.person.name(),
|
||
|
|
'update_time': DateTime.now().microsecondsSinceEpoch
|
||
|
|
}, merge: true);
|
||
|
|
}
|
||
|
|
|
||
|
|
void remove() {
|
||
|
|
Firestore.instance.collection('tests').document(tests[0].id).setData(
|
||
|
|
{'deleted': 1, 'update_time': DateTime.now().microsecondsSinceEpoch},
|
||
|
|
merge: true);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
void logout() {
|
||
|
|
_clearState();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class Test {
|
||
|
|
String id;
|
||
|
|
String name;
|
||
|
|
double age;
|
||
|
|
int updateTime;
|
||
|
|
Test(this.id, {this.name, this.age, this.updateTime});
|
||
|
|
|
||
|
|
factory Test.fromMap(Map<String, dynamic> map, String id) {
|
||
|
|
return Test(id,
|
||
|
|
name: map['name'], age: map['age'], updateTime: map['update_time']);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
bool operator ==(other) {
|
||
|
|
if (identical(this, other)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return other.id == this.id;
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
int get hashCode {
|
||
|
|
int result = 17;
|
||
|
|
result = 37 * result + id.hashCode;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
}
|