[Web] Fix missing MatrixState in context because of wrong order in widget tree

Took 21 minutes
This commit is contained in:
Marcel 2020-01-23 11:11:57 +00:00 committed by Christian Pauly
parent a512dc6dbd
commit a980217779
10 changed files with 114 additions and 90 deletions

View File

@ -346,10 +346,12 @@ class MatrixState extends State<Matrix> {
@override @override
void initState() { void initState() {
if (widget.client == null) { if (widget.client == null) {
print("[Matrix] Init matrix client");
client = Client(widget.clientName, debug: false); client = Client(widget.clientName, debug: false);
if (!kIsWeb) { if (!kIsWeb) {
_initWithStore(); _initWithStore();
} else { } else {
print("[Web] Web platform detected - Store disabled!");
loadAccount(); loadAccount();
} }
} else { } else {

View File

@ -20,46 +20,46 @@ class App extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Matrix( return Matrix(
clientName: "FluffyChat", clientName: "FluffyChat",
child: MaterialApp( child: Builder(
title: 'FluffyChat', builder: (BuildContext context) => MaterialApp(
theme: ThemeData( title: 'FluffyChat',
brightness: Brightness.light, theme: ThemeData(
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, brightness: Brightness.light,
color: Colors.white, primaryColor: Color(0xFF5625BA),
elevation: 1, backgroundColor: Colors.white,
textTheme: TextTheme( secondaryHeaderColor: Color(0xFFF0F0F0),
title: TextStyle(color: Colors.black), 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: [
localizationsDelegates: [ AppLocalizationsDelegate(),
AppLocalizationsDelegate(), GlobalMaterialLocalizations.delegate,
GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, ],
], supportedLocales: [
supportedLocales: [ const Locale('en'), // English
const Locale('en'), // English const Locale('de'), // German
const Locale('de'), // German ],
], home: FutureBuilder<LoginState>(
home: Builder(
builder: (BuildContext context) => FutureBuilder<LoginState>(
future: Matrix.of(context).client.onLoginStateChanged.stream.first, future: Matrix.of(context).client.onLoginStateChanged.stream.first,
builder: (context, snapshot) { builder: (context, snapshot) {
if (!snapshot.hasData) { if (!snapshot.hasData) {

View File

@ -7,7 +7,7 @@ extension LocalizedRoomDisplayname on Room {
if ((this.name?.isEmpty ?? true) && if ((this.name?.isEmpty ?? true) &&
(this.canonicalAlias?.isEmpty ?? true) && (this.canonicalAlias?.isEmpty ?? true) &&
!this.isDirectChat && !this.isDirectChat &&
this.mHeroes.isNotEmpty) { (this.mHeroes != null && this.mHeroes.isNotEmpty)) {
return I18n.of(context).groupWith(this.displayname); return I18n.of(context).groupWith(this.displayname);
} }
return this.displayname; return this.displayname;

View File

@ -20,6 +20,7 @@ class Chat extends StatefulWidget {
final String id; final String id;
const Chat(this.id, {Key key}) : super(key: key); const Chat(this.id, {Key key}) : super(key: key);
@override @override
_ChatState createState() => _ChatState(); _ChatState createState() => _ChatState();
} }
@ -55,6 +56,8 @@ class _ChatState extends State<Chat> {
} }
void updateView() { void updateView() {
if (!mounted) return;
String seenByText = ""; String seenByText = "";
if (timeline.events.isNotEmpty) { if (timeline.events.isNotEmpty) {
List lastReceipts = List.from(timeline.events.first.receipts); List lastReceipts = List.from(timeline.events.first.receipts);
@ -74,9 +77,11 @@ class _ChatState extends State<Chat> {
(lastReceipts.length - 1).toString()); (lastReceipts.length - 1).toString());
} }
} }
setState(() { if (timeline != null) {
this.seenByText = seenByText; setState(() {
}); this.seenByText = seenByText;
});
}
} }
Future<bool> getTimeline() async { Future<bool> getTimeline() async {
@ -88,6 +93,7 @@ class _ChatState extends State<Chat> {
@override @override
void dispose() { void dispose() {
timeline?.sub?.cancel(); timeline?.sub?.cancel();
timeline = null;
matrix.activeRoomId = ""; matrix.activeRoomId = "";
super.dispose(); super.dispose();
} }
@ -243,38 +249,42 @@ class _ChatState extends State<Chat> {
timeline.events.isNotEmpty) { timeline.events.isNotEmpty) {
room.sendReadReceipt(timeline.events[0].eventId); room.sendReadReceipt(timeline.events[0].eventId);
} }
if (timeline.events.isEmpty) return Container();
return ListView.builder( return ListView.builder(
reverse: true, reverse: true,
itemCount: timeline.events.length + 1, itemCount: timeline.events.length + 1,
controller: _scrollController, controller: _scrollController,
itemBuilder: (BuildContext context, int i) => i == 0 itemBuilder: (BuildContext context, int i) {
? AnimatedContainer( return i == 0
height: seenByText.isEmpty ? 0 : 24, ? AnimatedContainer(
duration: seenByText.isEmpty height: seenByText.isEmpty ? 0 : 24,
? Duration(milliseconds: 0) duration: seenByText.isEmpty
: Duration(milliseconds: 500), ? Duration(milliseconds: 0)
alignment: timeline.events.first.senderId == : Duration(milliseconds: 500),
client.userID alignment: timeline.events.first.senderId ==
? Alignment.topRight client.userID
: Alignment.topLeft, ? Alignment.topRight
child: Text( : Alignment.topLeft,
seenByText, child: Text(
maxLines: 1, seenByText,
overflow: TextOverflow.ellipsis, maxLines: 1,
style: TextStyle( overflow: TextOverflow.ellipsis,
color: Theme.of(context).primaryColor, style: TextStyle(
), color: Theme.of(context).primaryColor,
), ),
padding: EdgeInsets.only( ),
left: 8, padding: EdgeInsets.only(
right: 8, left: 8,
bottom: 8, right: 8,
), bottom: 8,
) ),
: Message(timeline.events[i - 1], )
nextEvent: : Message(timeline.events[i - 1],
i >= 2 ? timeline.events[i - 2] : null), nextEvent:
); i >= 2 ? timeline.events[i - 2] : null);
});
}, },
), ),
), ),

View File

@ -13,6 +13,7 @@ import 'package:fluffychat/utils/room_extension.dart';
import 'package:fluffychat/utils/room_state_enums_extensions.dart'; import 'package:fluffychat/utils/room_state_enums_extensions.dart';
import 'package:fluffychat/views/chat_list.dart'; import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/invitation_selection.dart'; import 'package:fluffychat/views/invitation_selection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@ -181,9 +182,10 @@ class _ChatDetailsState extends State<ChatDetails> {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
ContentBanner(widget.room.avatar, ContentBanner(widget.room.avatar,
onEdit: widget.room.canSendEvent("m.room.avatar") onEdit:
? () => setAvatarAction(context) widget.room.canSendEvent("m.room.avatar") && !kIsWeb
: null), ? () => setAvatarAction(context)
: null),
Divider(height: 1), Divider(height: 1),
topicEditMode topicEditMode
? ListTile( ? ListTile(

View File

@ -11,6 +11,7 @@ import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/utils/url_launcher.dart';
import 'package:fluffychat/views/archive.dart'; import 'package:fluffychat/views/archive.dart';
import 'package:fluffychat/views/settings.dart'; import 'package:fluffychat/views/settings.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart';
@ -51,7 +52,8 @@ class _ChatListState extends State<ChatList> {
if (client.prevBatch?.isEmpty ?? true) { if (client.prevBatch?.isEmpty ?? true) {
await client.onFirstSync.stream.first; 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; return true;
} }
@ -60,13 +62,16 @@ class _ChatListState extends State<ChatList> {
searchController.addListener( searchController.addListener(
() => setState(() => null), () => setState(() => null),
); );
getSharedData(); if (kIsWeb) {
getSharedData();
}
super.initState(); super.initState();
} }
StreamSubscription _intentDataStreamSubscription; StreamSubscription _intentDataStreamSubscription;
void processSharedText(String text) { void processSharedText(String text) {
if (text?.isEmpty ?? true) return;
if (text.startsWith("https://matrix.to/#/")) { if (text.startsWith("https://matrix.to/#/")) {
UrlLauncher(context, text).openMatrixToUrl(); UrlLauncher(context, text).openMatrixToUrl();
} else { } else {

View File

@ -4,6 +4,7 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/components/matrix.dart'; import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/i18n/i18n.dart'; import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/utils/app_route.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'chat_list.dart'; import 'chat_list.dart';
@ -73,16 +74,19 @@ class _LoginState extends State<Login> {
setState(() => passwordError = exception.toString()); setState(() => passwordError = exception.toString());
return setState(() => loading = false); return setState(() => loading = false);
} }
try { if (!kIsWeb) {
print("[Login] Setup Firebase..."); try {
await matrix.setupFirebase(); print("[Login] Setup Firebase...");
} catch (exception) { await matrix.setupFirebase();
print("[Login] Failed to setup Firebase. Logout now..."); } catch (exception) {
await matrix.client.logout(); print("[Login] Failed to setup Firebase. Logout now...");
matrix.clean(); await matrix.client.logout();
setState(() => passwordError = exception.toString()); matrix.clean();
return setState(() => loading = false); setState(() => passwordError = exception.toString());
return setState(() => loading = false);
}
} }
print("[Login] Store account and go to ChatListView"); print("[Login] Store account and go to ChatListView");
await Matrix.of(context).saveAccount(); await Matrix.of(context).saveAccount();
setState(() => loading = false); setState(() => loading = false);

View File

@ -8,6 +8,7 @@ import 'package:fluffychat/i18n/i18n.dart';
import 'package:fluffychat/utils/app_route.dart'; import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/views/chat_list.dart'; import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/sign_up.dart'; import 'package:fluffychat/views/sign_up.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:toast/toast.dart'; import 'package:toast/toast.dart';
@ -106,7 +107,7 @@ class _SettingsState extends State<Settings> {
profile?.avatarUrl ?? MxContent(""), profile?.avatarUrl ?? MxContent(""),
defaultIcon: Icons.account_circle, defaultIcon: Icons.account_circle,
loading: profile == null, loading: profile == null,
onEdit: () => setAvatarAction(context), onEdit: kIsWeb ? null : () => setAvatarAction(context),
), ),
ListTile( ListTile(
leading: Icon(Icons.edit), leading: Icon(Icons.edit),

View File

@ -110,8 +110,8 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: "2545995bbe96a1d96fe176ab666f4dd03d591aa6" ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4
resolved-ref: "2545995bbe96a1d96fe176ab666f4dd03d591aa6" resolved-ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4
url: "https://gitlab.com/famedly/famedlysdk.git" url: "https://gitlab.com/famedly/famedlysdk.git"
source: git source: git
version: "0.0.1" version: "0.0.1"

View File

@ -27,7 +27,7 @@ dependencies:
famedlysdk: famedlysdk:
git: git:
url: https://gitlab.com/famedly/famedlysdk.git url: https://gitlab.com/famedly/famedlysdk.git
ref: 2545995bbe96a1d96fe176ab666f4dd03d591aa6 ref: bc2ca9749cfcc0506c59f97f4ae4987f0e84fbf4
localstorage: ^3.0.1+4 localstorage: ^3.0.1+4
bubble: ^1.1.9+1 bubble: ^1.1.9+1