From cf15aae5acd592003f1d6a34beb89d2386906fe4 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 19 Apr 2022 02:33:56 +0300 Subject: [PATCH] Implement thread list update feature --- lib/main.dart | 14 ++++++++++++++ lib/thread_list_model.dart | 31 +++++++++++++++++++++--------- lib/thread_list_view.dart | 39 ++++++++++++++------------------------ 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 7c5e281..91274cb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -93,6 +93,20 @@ class _MyHomePageState extends State { // Here we take the value from the MyHomePage object that was created by // the App.build method, and use it to set our appbar title. title: Text(widget.title), + actions: [ + TextButton.icon( + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Обновление списка тредов...')), + ); + Provider.of(context, listen: false).update(); + }, + label: const Text("Обновить"), + style: TextButton.styleFrom( + primary: Theme.of(context).colorScheme.onPrimary), + icon: Icon(Icons.sync)) + ], ), body: Center( child: Container( diff --git a/lib/thread_list_model.dart b/lib/thread_list_model.dart index 028a3ee..4dd2350 100644 --- a/lib/thread_list_model.dart +++ b/lib/thread_list_model.dart @@ -6,6 +6,8 @@ class ThreadListModel extends ChangeNotifier { String currentGroup = ""; NNTPClient? client; Map>> threads = {}; + int _pageNum = -1; + List _curItems = []; Future selectNewsgroup(String name) async { if (currentGroup == name) return; @@ -13,27 +15,29 @@ class ThreadListModel extends ChangeNotifier { currentGroup = name; await client!.selectGroup(name); threads.putIfAbsent(name, () => {}); + _curItems.clear(); + _pageNum = -1; notifyListeners(); } - Future> getNewThreads( - int perPage, int pageNum, bool clearCache) async { + Future> getNewThreads(bool clearCache) async { if (currentGroup == "") return []; - List items = []; + + _pageNum += 1; if (clearCache) { threads[currentGroup]?.clear(); } - if (threads[currentGroup]!.containsKey(pageNum)) { - items.addAll(threads[currentGroup]![pageNum]!); + if (threads[currentGroup]!.containsKey(_pageNum)) { + _curItems.addAll(threads[currentGroup]![_pageNum]!); } else { - var resp = await client!.getNewThreads(perPage, pageNum); + var resp = await client!.getNewThreads(10, _pageNum); resp.forEach((pair) { var number = pair.item1; var msg = pair.item2; - items.add(ThreadItem( + _curItems.add(ThreadItem( msg.getHeaderValue("Message-Id")!, number, msg.getHeaderValue("Subject")!, @@ -42,9 +46,18 @@ class ThreadListModel extends ChangeNotifier { msg.decodeTextPlainPart()!)); }); - threads[currentGroup]![pageNum] = items; + if (resp.isEmpty) _pageNum -= 1; + + threads[currentGroup]![_pageNum] = List.from(_curItems); } - return items; + return _curItems; + } + + void update() { + _curItems.clear(); + _pageNum = -1; + threads[currentGroup]!.clear(); + notifyListeners(); } } diff --git a/lib/thread_list_view.dart b/lib/thread_list_view.dart index 5c45ff7..8770b76 100644 --- a/lib/thread_list_view.dart +++ b/lib/thread_list_view.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:wind/thread_list_model.dart'; -import 'package:wind/thread_screen.dart'; class ThreadListView extends StatefulWidget { @override @@ -9,8 +8,6 @@ class ThreadListView extends StatefulWidget { } class ThreadListViewState extends State { - List _items = []; - int _pageNum = 0; String _curGroup = ""; @override @@ -24,16 +21,13 @@ class ThreadListViewState extends State { if (snapshot.hasData && snapshot.connectionState != ConnectionState.waiting) { List data = List.from(snapshot.data!); - _items.addAll(data); - if (_items.isNotEmpty && - _items.last.number != -100500 && - data.isNotEmpty) - _items.add(ThreadItem("", -100500, "", "", "", + if (data.isNotEmpty && data.last.number != -100500) + data.add(ThreadItem("", -100500, "", "", "", "")); // magic item (for button "load more") return _curGroup != "" - ? _threadView() + ? _threadView(data) : Center( - child: Text("Newsgroup is not selected", + child: Text("Новостная группа не выбрана", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16))); } else if (snapshot.hasError) { @@ -46,22 +40,18 @@ class ThreadListViewState extends State { Future> _fetchThreadList(BuildContext context) async { var model = context.read(); - if (model.currentGroup != _curGroup) { - _items.clear(); - _curGroup = model.currentGroup; - _pageNum = 0; - } - return await model.getNewThreads(10, _pageNum, false); + _curGroup = model.currentGroup; + return await model.getNewThreads(false); } - Widget _threadView() { - return _items.isNotEmpty + Widget _threadView(List items) { + return items.isNotEmpty ? Scrollbar( child: ListView.builder( key: PageStorageKey("threadList"), - itemCount: _items.length, + itemCount: items.length, itemBuilder: (context, index) { - if (_items[index].number == -100500) { + if (items[index].number == -100500) { return Container( height: 100, padding: EdgeInsets.all(20), @@ -72,19 +62,18 @@ class ThreadListViewState extends State { ), onPressed: () { setState(() { - _pageNum += 1; - _items.removeLast(); + items.removeLast(); }); }, - child: Text('Load more'), + child: Text('Загрузить больше'), ), ); } else - return ThreadListItemView(item: _items[index]); + return ThreadListItemView(item: items[index]); }), ) : Center( - child: Text("This newsgroup is empty", + child: Text("Эта новостная группа пуста", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16))); } }