From a9802177794aeaa9992776a9adadbd1c7a4241af Mon Sep 17 00:00:00 2001 From: Marcel Date: Thu, 23 Jan 2020 11:11:57 +0000 Subject: [PATCH] [Web] Fix missing MatrixState in context because of wrong order in widget tree Took 21 minutes --- lib/components/matrix.dart | 2 + lib/main.dart | 74 ++++++++++++++++----------------- lib/utils/room_extension.dart | 2 +- lib/views/chat.dart | 78 ++++++++++++++++++++--------------- lib/views/chat_details.dart | 8 ++-- lib/views/chat_list.dart | 9 +++- lib/views/login.dart | 22 ++++++---- lib/views/settings.dart | 3 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- 10 files changed, 114 insertions(+), 90 deletions(-) diff --git a/lib/components/matrix.dart b/lib/components/matrix.dart index 42ebc9c4..6a7d7d7e 100644 --- a/lib/components/matrix.dart +++ b/lib/components/matrix.dart @@ -346,10 +346,12 @@ class MatrixState extends State { @override void initState() { if (widget.client == null) { + print("[Matrix] Init matrix client"); client = Client(widget.clientName, debug: false); if (!kIsWeb) { _initWithStore(); } else { + print("[Web] Web platform detected - Store disabled!"); loadAccount(); } } else { diff --git a/lib/main.dart b/lib/main.dart index 65300c64..dba65163 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,46 +20,46 @@ class App extends StatelessWidget { Widget build(BuildContext context) { return Matrix( clientName: "FluffyChat", - child: MaterialApp( - title: 'FluffyChat', - theme: ThemeData( - brightness: Brightness.light, - primaryColor: Color(0xFF5625BA), - backgroundColor: Colors.white, - secondaryHeaderColor: Color(0xFFF0F0F0), - scaffoldBackgroundColor: Colors.white, - dialogTheme: DialogTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - ), - popupMenuTheme: PopupMenuThemeData( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - ), - appBarTheme: AppBarTheme( + child: Builder( + builder: (BuildContext context) => MaterialApp( + title: 'FluffyChat', + theme: ThemeData( brightness: Brightness.light, - color: Colors.white, - elevation: 1, - textTheme: TextTheme( - title: TextStyle(color: Colors.black), + primaryColor: Color(0xFF5625BA), + backgroundColor: Colors.white, + secondaryHeaderColor: Color(0xFFF0F0F0), + scaffoldBackgroundColor: Colors.white, + dialogTheme: DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + popupMenuTheme: PopupMenuThemeData( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + appBarTheme: AppBarTheme( + brightness: Brightness.light, + color: Colors.white, + elevation: 1, + textTheme: TextTheme( + title: TextStyle(color: Colors.black), + ), + iconTheme: IconThemeData(color: Colors.black), ), - iconTheme: IconThemeData(color: Colors.black), ), - ), - localizationsDelegates: [ - AppLocalizationsDelegate(), - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: [ - const Locale('en'), // English - const Locale('de'), // German - ], - home: Builder( - builder: (BuildContext context) => FutureBuilder( + localizationsDelegates: [ + AppLocalizationsDelegate(), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: [ + const Locale('en'), // English + const Locale('de'), // German + ], + home: FutureBuilder( future: Matrix.of(context).client.onLoginStateChanged.stream.first, builder: (context, snapshot) { if (!snapshot.hasData) { diff --git a/lib/utils/room_extension.dart b/lib/utils/room_extension.dart index af08da0a..5d60ed1c 100644 --- a/lib/utils/room_extension.dart +++ b/lib/utils/room_extension.dart @@ -7,7 +7,7 @@ extension LocalizedRoomDisplayname on Room { if ((this.name?.isEmpty ?? true) && (this.canonicalAlias?.isEmpty ?? true) && !this.isDirectChat && - this.mHeroes.isNotEmpty) { + (this.mHeroes != null && this.mHeroes.isNotEmpty)) { return I18n.of(context).groupWith(this.displayname); } return this.displayname; diff --git a/lib/views/chat.dart b/lib/views/chat.dart index 34265263..c3f811f6 100644 --- a/lib/views/chat.dart +++ b/lib/views/chat.dart @@ -20,6 +20,7 @@ class Chat extends StatefulWidget { final String id; const Chat(this.id, {Key key}) : super(key: key); + @override _ChatState createState() => _ChatState(); } @@ -55,6 +56,8 @@ class _ChatState extends State { } void updateView() { + if (!mounted) return; + String seenByText = ""; if (timeline.events.isNotEmpty) { List lastReceipts = List.from(timeline.events.first.receipts); @@ -74,9 +77,11 @@ class _ChatState extends State { (lastReceipts.length - 1).toString()); } } - setState(() { - this.seenByText = seenByText; - }); + if (timeline != null) { + setState(() { + this.seenByText = seenByText; + }); + } } Future getTimeline() async { @@ -88,6 +93,7 @@ class _ChatState extends State { @override void dispose() { timeline?.sub?.cancel(); + timeline = null; matrix.activeRoomId = ""; super.dispose(); } @@ -243,38 +249,42 @@ class _ChatState extends State { timeline.events.isNotEmpty) { room.sendReadReceipt(timeline.events[0].eventId); } + + if (timeline.events.isEmpty) return Container(); + return ListView.builder( - reverse: true, - itemCount: timeline.events.length + 1, - controller: _scrollController, - itemBuilder: (BuildContext context, int i) => i == 0 - ? AnimatedContainer( - height: seenByText.isEmpty ? 0 : 24, - duration: seenByText.isEmpty - ? Duration(milliseconds: 0) - : Duration(milliseconds: 500), - alignment: timeline.events.first.senderId == - client.userID - ? Alignment.topRight - : Alignment.topLeft, - child: Text( - seenByText, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).primaryColor, - ), - ), - padding: EdgeInsets.only( - left: 8, - right: 8, - bottom: 8, - ), - ) - : Message(timeline.events[i - 1], - nextEvent: - i >= 2 ? timeline.events[i - 2] : null), - ); + reverse: true, + itemCount: timeline.events.length + 1, + controller: _scrollController, + itemBuilder: (BuildContext context, int i) { + return i == 0 + ? AnimatedContainer( + height: seenByText.isEmpty ? 0 : 24, + duration: seenByText.isEmpty + ? Duration(milliseconds: 0) + : Duration(milliseconds: 500), + alignment: timeline.events.first.senderId == + client.userID + ? Alignment.topRight + : Alignment.topLeft, + child: Text( + seenByText, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context).primaryColor, + ), + ), + padding: EdgeInsets.only( + left: 8, + right: 8, + bottom: 8, + ), + ) + : Message(timeline.events[i - 1], + nextEvent: + i >= 2 ? timeline.events[i - 2] : null); + }); }, ), ), diff --git a/lib/views/chat_details.dart b/lib/views/chat_details.dart index 4422d79b..4fa7ac7d 100644 --- a/lib/views/chat_details.dart +++ b/lib/views/chat_details.dart @@ -13,6 +13,7 @@ import 'package:fluffychat/utils/room_extension.dart'; import 'package:fluffychat/utils/room_state_enums_extensions.dart'; import 'package:fluffychat/views/chat_list.dart'; import 'package:fluffychat/views/invitation_selection.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:image_picker/image_picker.dart'; @@ -181,9 +182,10 @@ class _ChatDetailsState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ContentBanner(widget.room.avatar, - onEdit: widget.room.canSendEvent("m.room.avatar") - ? () => setAvatarAction(context) - : null), + onEdit: + widget.room.canSendEvent("m.room.avatar") && !kIsWeb + ? () => setAvatarAction(context) + : null), Divider(height: 1), topicEditMode ? ListTile( diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart index d05acdbf..36948150 100644 --- a/lib/views/chat_list.dart +++ b/lib/views/chat_list.dart @@ -11,6 +11,7 @@ import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/views/archive.dart'; import 'package:fluffychat/views/settings.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; @@ -51,7 +52,8 @@ class _ChatListState extends State { if (client.prevBatch?.isEmpty ?? true) { await client.onFirstSync.stream.first; } - sub ??= client.onSync.stream.listen((s) => setState(() => null)); + sub ??= client.onSync.stream + .listen((s) => mounted ? setState(() => null) : null); return true; } @@ -60,13 +62,16 @@ class _ChatListState extends State { searchController.addListener( () => setState(() => null), ); - getSharedData(); + if (kIsWeb) { + getSharedData(); + } super.initState(); } StreamSubscription _intentDataStreamSubscription; void processSharedText(String text) { + if (text?.isEmpty ?? true) return; if (text.startsWith("https://matrix.to/#/")) { UrlLauncher(context, text).openMatrixToUrl(); } else { diff --git a/lib/views/login.dart b/lib/views/login.dart index 24ffe374..bb5ce3eb 100644 --- a/lib/views/login.dart +++ b/lib/views/login.dart @@ -4,6 +4,7 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/components/matrix.dart'; import 'package:fluffychat/i18n/i18n.dart'; import 'package:fluffychat/utils/app_route.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'chat_list.dart'; @@ -73,16 +74,19 @@ class _LoginState extends State { setState(() => passwordError = exception.toString()); return setState(() => loading = false); } - try { - print("[Login] Setup Firebase..."); - await matrix.setupFirebase(); - } catch (exception) { - print("[Login] Failed to setup Firebase. Logout now..."); - await matrix.client.logout(); - matrix.clean(); - setState(() => passwordError = exception.toString()); - return setState(() => loading = false); + if (!kIsWeb) { + try { + print("[Login] Setup Firebase..."); + await matrix.setupFirebase(); + } catch (exception) { + print("[Login] Failed to setup Firebase. Logout now..."); + await matrix.client.logout(); + matrix.clean(); + setState(() => passwordError = exception.toString()); + return setState(() => loading = false); + } } + print("[Login] Store account and go to ChatListView"); await Matrix.of(context).saveAccount(); setState(() => loading = false); diff --git a/lib/views/settings.dart b/lib/views/settings.dart index 8be962e3..ba711788 100644 --- a/lib/views/settings.dart +++ b/lib/views/settings.dart @@ -8,6 +8,7 @@ import 'package:fluffychat/i18n/i18n.dart'; import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/views/chat_list.dart'; import 'package:fluffychat/views/sign_up.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:toast/toast.dart'; @@ -106,7 +107,7 @@ class _SettingsState extends State { profile?.avatarUrl ?? MxContent(""), defaultIcon: Icons.account_circle, loading: profile == null, - onEdit: () => setAvatarAction(context), + onEdit: kIsWeb ? null : () => setAvatarAction(context), ), ListTile( leading: Icon(Icons.edit), diff --git a/pubspec.lock b/pubspec.lock index dd06d002..baaabb91 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -110,8 +110,8 @@ packages: dependency: "direct main" description: path: "." - ref: "2545995bbe96a1d96fe176ab666f4dd03d591aa6" - resolved-ref: "2545995bbe96a1d96fe176ab666f4dd03d591aa6" + ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4 + resolved-ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4 url: "https://gitlab.com/famedly/famedlysdk.git" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index 4e04c1d8..14b7a029 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -27,7 +27,7 @@ dependencies: famedlysdk: git: url: https://gitlab.com/famedly/famedlysdk.git - ref: 2545995bbe96a1d96fe176ab666f4dd03d591aa6 + ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4 localstorage: ^3.0.1+4 bubble: ^1.1.9+1