~cytrogen/fluent-reader-mobile

ref: b39dfad9d08734897c1271b30d4ce8decea2bdd3 fluent-reader-mobile/lib/models/items_model.dart -rw-r--r-- 4.0 KiB
b39dfad9 — Preckrasno Add Ukrainian (ua) translation (#53) 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import 'package:fluent_reader_lite/models/item.dart';
import 'package:fluent_reader_lite/utils/global.dart';
import 'package:flutter/cupertino.dart';
import 'package:sqflite/sqflite.dart';

class ItemsModel with ChangeNotifier {
  Map<String, RSSItem> _items = Map();

  bool has(String id) => _items.containsKey(id);

  RSSItem getItem(String id) => _items[id];
  Iterable<RSSItem> getItems() => _items.values;

  void loadItems(Iterable<RSSItem> items) {
    for (var item in items) {
      _items[item.id] = item;
    }
  }

  Future<void> updateItem(String iid, 
    {Batch batch, bool read, bool starred, local: false}) async {
    Map<String, dynamic> updateMap = Map();
    if (_items.containsKey(iid)) {
      final item = _items[iid].clone();
      if (read != null) {
        item.hasRead = read;
        if (!local) {
          if (read) Global.service.markRead(item);
          else Global.service.markUnread(item);
        }
        Global.sourcesModel.updateUnreadCount(item.source, read ? -1 : 1);
      }
      if (starred != null) {
        item.starred = starred;
        if (!local) {
          if (starred) Global.service.star(item);
          else Global.service.unstar(item);
        }
      }
      _items[iid] = item;
    }
    if (read != null) updateMap["hasRead"] = read ? 1 : 0;
    if (starred != null) updateMap["starred"] = starred ? 1 : 0;
    if (batch != null) {
      batch.update("items", updateMap, where: "iid = ?", whereArgs: [iid]);
    } else {
      notifyListeners();
      await Global.db.update("items", updateMap, where: "iid = ?", whereArgs: [iid]);
    }
  }

  Future<void> markAllRead(Set<String> sids, {DateTime date, before = true}) async {
    Global.service.markAllRead(sids, date, before);
    List<String> predicates = ["hasRead = 0"];
    if (sids.length > 0) {
      predicates.add("source IN (${List.filled(sids.length, "?").join(" , ")})");
    }
    if (date != null) {
      predicates.add("date ${before ? "<=" : ">="} ${date.millisecondsSinceEpoch}");
    }
    await Global.db.update(
      "items",
      { "hasRead": 1 },
      where: predicates.join(" AND "),
      whereArgs: sids.toList(),
    );
    for (var item in _items.values.toList()) {
      if (sids.length > 0 && !sids.contains(item.source)) continue;
      if (date != null && 
        (before ? item.date.compareTo(date) > 0 : item.date.compareTo(date) < 0))
        continue;
      item.hasRead = true;
    }
    notifyListeners();
    Global.sourcesModel.updateUnreadCounts();
  }

  Future<void> fetchItems() async {
    final items = await Global.service.fetchItems();
    final batch = Global.db.batch();
    for (var item in items) {
      if (!Global.sourcesModel.has(item.source)) continue;
      _items[item.id] = item;
      batch.insert(
        "items",
        item.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace,
      );
    }
    await batch.commit(noResult: true);
    // notifyListeners();
    Global.sourcesModel.updateWithFetchedItems(items);
    Global.feedsModel.addFetchedItems(items);
  }

  Future<void> syncItems() async {
    final tuple = await Global.service.syncItems();
    final unreadIds = tuple.item1;
    final starredIds = tuple.item2;
    final rows = await Global.db.query(
      "items",
      columns: ["iid", "hasRead", "starred"],
      where: "hasRead = 0 OR starred = 1",
    );
    final batch = Global.db.batch();
    for (var row in rows) {
      final id = row["iid"];
      if (row["hasRead"] == 0 && !unreadIds.remove(id)) {
        await updateItem(id, read: true, batch: batch, local: true);
      }
      if (row["starred"] == 1 && !starredIds.remove(id)) {
        await updateItem(id, starred: false, batch: batch, local: true);
      }
    }
    for (var unread in unreadIds) {
      await updateItem(unread, read: false, batch: batch, local: true);
    }
    for (var starred in starredIds) {
      await updateItem(starred, starred: true, batch: batch, local: true);
    }
    notifyListeners();
    await batch.commit(noResult: true);
    await Global.sourcesModel.updateUnreadCounts();
  }
}