diff --git a/lib/components/connection_status_header.dart b/lib/components/connection_status_header.dart new file mode 100644 index 0000000..705a4f5 --- /dev/null +++ b/lib/components/connection_status_header.dart @@ -0,0 +1,44 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; + +import 'matrix.dart'; + +class ConnectionStatusHeader extends StatefulWidget { + @override + _ConnectionStatusHeaderState createState() => _ConnectionStatusHeaderState(); +} + +class _ConnectionStatusHeaderState extends State { + StreamSubscription _onSyncSub; + StreamSubscription _onSyncErrorSub; + static bool _connected = false; + + set connected(bool connected) { + if (mounted) { + setState(() => _connected = connected); + } + } + + @override + void dispose() { + _onSyncSub?.cancel(); + _onSyncErrorSub?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _onSyncSub ??= Matrix.of(context).client.onSync.stream.listen( + (_) => connected = true, + ); + _onSyncErrorSub ??= Matrix.of(context).client.onSyncError.stream.listen( + (_) => connected = false, + ); + + return AnimatedContainer( + duration: Duration(milliseconds: 500), + height: _connected ? 0 : 5, + child: LinearProgressIndicator(), + ); + } +} diff --git a/lib/views/chat.dart b/lib/views/chat.dart index c35a733..70c6c53 100644 --- a/lib/views/chat.dart +++ b/lib/views/chat.dart @@ -6,6 +6,7 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/components/adaptive_page_layout.dart'; import 'package:fluffychat/components/avatar.dart'; import 'package:fluffychat/components/chat_settings_popup_menu.dart'; +import 'package:fluffychat/components/connection_status_header.dart'; import 'package:fluffychat/components/dialogs/presence_dialog.dart'; import 'package:fluffychat/components/dialogs/recording_dialog.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; @@ -90,11 +91,11 @@ class _ChatState extends State<_Chat> { void requestHistory() async { if (_canLoadMore) { setState(() => _loadingHistory = true); - try { - await timeline.requestHistory(historyCount: _loadHistoryCount); - } catch (e) { - debugPrint('Error loading history: ' + e.toString()); - } + + await SimpleDialogs(context).tryRequestWithErrorToast( + timeline.requestHistory(historyCount: _loadHistoryCount), + ); + if (mounted) setState(() => _loadingHistory = false); } } @@ -452,7 +453,6 @@ class _ChatState extends State<_Chat> { ), Column( children: [ - if (_loadingHistory) LinearProgressIndicator(), Expanded( child: FutureBuilder( future: getTimeline(), @@ -486,19 +486,28 @@ class _ChatState extends State<_Chat> { controller: _scrollController, itemBuilder: (BuildContext context, int i) { return i == timeline.events.length + 1 - ? _canLoadMore && !_loadingHistory - ? FlatButton( - child: Text( - L10n.of(context).loadMore, - style: TextStyle( - color: Theme.of(context).primaryColor, - fontWeight: FontWeight.bold, - decoration: TextDecoration.underline, - ), - ), - onPressed: requestHistory, + ? _loadingHistory + ? Container( + height: 50, + alignment: Alignment.center, + padding: EdgeInsets.all(8), + child: CircularProgressIndicator(), ) - : Container() + : _canLoadMore + ? FlatButton( + child: Text( + L10n.of(context).loadMore, + style: TextStyle( + color: Theme.of(context) + .primaryColor, + fontWeight: FontWeight.bold, + decoration: + TextDecoration.underline, + ), + ), + onPressed: requestHistory, + ) + : Container() : i == 0 ? AnimatedContainer( height: seenByText.isEmpty ? 0 : 24, @@ -556,6 +565,7 @@ class _ChatState extends State<_Chat> { }, ), ), + ConnectionStatusHeader(), AnimatedContainer( duration: Duration(milliseconds: 300), height: replyEvent != null ? 56 : 0, diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart index ee90f9c..93a78ab 100644 --- a/lib/views/chat_list.dart +++ b/lib/views/chat_list.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/matrix_api.dart'; +import 'package:fluffychat/components/connection_status_header.dart'; import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; import 'package:fluffychat/components/list_items/presence_list_item.dart'; import 'package:fluffychat/components/list_items/public_room_list_item.dart'; @@ -408,26 +409,34 @@ class _ChatListState extends State { itemCount: totalCount + 1, itemBuilder: (BuildContext context, int i) { if (i == 0) { - return (directChats.isEmpty || - selectMode == SelectMode.share) - ? Container() - : PreferredSize( - preferredSize: - Size.fromHeight(90), - child: Container( - height: 82, - child: ListView.builder( - scrollDirection: - Axis.horizontal, - itemCount: directChats.length, - itemBuilder: - (BuildContext context, + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + ConnectionStatusHeader(), + (directChats.isEmpty || + selectMode == + SelectMode.share) + ? Container() + : PreferredSize( + preferredSize: + Size.fromHeight(90), + child: Container( + height: 82, + child: ListView.builder( + scrollDirection: + Axis.horizontal, + itemCount: + directChats.length, + itemBuilder: (BuildContext + context, int i) => PresenceListItem( directChats[i]), + ), + ), ), - ), - ); + ], + ); } i--; return i < rooms.length