Merge branch 'main' of gitlab.com:famedly/fluffychat

This commit is contained in:
Christian Pauly 2021-05-23 13:28:55 +02:00
commit 8fce5c0c4f
11 changed files with 147 additions and 117 deletions

View file

@ -1352,7 +1352,7 @@
"senderName": {} "senderName": {}
} }
}, },
"startYourFirstChat": "Zahajte svůj první chat! 🙂\n- Klepněte na „+“\n- Zadejte uživatelské jméno přítele\n- Bavte se chatováním", "startYourFirstChat": "Zahajte svůj první chat! 🙂\n- Klepněte na tlačítko zprávy\n- Zadejte uživatelské jméno přítele\n- Bavte se chatováním",
"@startYourFirstChat": { "@startYourFirstChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2341,5 +2341,15 @@
"@invalidEmail": { "@invalidEmail": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
},
"useSSO": "Použijte jednotné přihlášení",
"@useSSO": {
"type": "text",
"placeholders": {}
},
"or": "Nebo",
"@or": {
"type": "text",
"placeholders": {}
} }
} }

View file

@ -1367,7 +1367,7 @@
"senderName": {} "senderName": {}
} }
}, },
"startYourFirstChat": "Alusta oma esimest vestlust kohe nüüd 🙂\n- Klõpsi „+“ ikooni\n- Sisesta teise osapoole kasutajanimi\n- Ja lase vestlusel kulgeda", "startYourFirstChat": "Alusta oma esimest vestlust kohe nüüd 🙂\n- klõpsi vestlusnuppu\n- sisesta teise osapoole kasutajanimi\n- ja lase vestlusel kulgeda",
"@startYourFirstChat": { "@startYourFirstChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2341,5 +2341,15 @@
"@invalidEmail": { "@invalidEmail": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
},
"or": "või",
"@or": {
"type": "text",
"placeholders": {}
},
"useSSO": "Kasuta ühekordset sisselogimist",
"@useSSO": {
"type": "text",
"placeholders": {}
} }
} }

View file

@ -1271,7 +1271,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"startYourFirstChat": "Hemen ilk sohbetinize başlayın! 🙂\n- \"+\" simgesine dokunun\n- Bir arkadaşın kullanıcı adını girin\n- Eğlenceli bir şekilde sohbet edin", "startYourFirstChat": "Hemen ilk sohbetinize başlayın! 🙂\n- Mesaj düğmesine dokunun\n- Bir arkadaşın kullanıcı adını girin\n- Eğlenceli bir şekilde sohbet edin",
"@startYourFirstChat": { "@startYourFirstChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2341,5 +2341,15 @@
"@invalidEmail": { "@invalidEmail": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
},
"useSSO": "Tekli oturum açma kullan",
"@useSSO": {
"type": "text",
"placeholders": {}
},
"or": "Veya",
"@or": {
"type": "text",
"placeholders": {}
} }
} }

View file

@ -65,6 +65,7 @@ class FluffyChatApp extends StatefulWidget {
} }
class _FluffyChatAppState extends State<FluffyChatApp> { class _FluffyChatAppState extends State<FluffyChatApp> {
final GlobalKey<MatrixState> _matrix = GlobalKey<MatrixState>();
GlobalKey<VRouterState> _router; GlobalKey<VRouterState> _router;
int columns; int columns;
String _initialUrl = '/'; String _initialUrl = '/';
@ -74,48 +75,49 @@ class _FluffyChatAppState extends State<FluffyChatApp> {
light: FluffyThemes.light, light: FluffyThemes.light,
dark: FluffyThemes.dark, dark: FluffyThemes.dark,
initial: AdaptiveThemeMode.system, initial: AdaptiveThemeMode.system,
builder: (theme, darkTheme) => Matrix( builder: (theme, darkTheme) => LayoutBuilder(
context: context, builder: (context, constraints) {
router: _router, var newColumns =
testClient: widget.testClient, (constraints.maxWidth / AppConfig.columnWidth).floor();
child: LayoutBuilder( if (newColumns > 3) newColumns = 3;
builder: (context, constraints) { columns ??= newColumns;
var newColumns = _router ??= GlobalKey<VRouterState>();
(constraints.maxWidth / AppConfig.columnWidth).floor(); if (columns != newColumns) {
if (newColumns > 3) newColumns = 3; WidgetsBinding.instance.addPostFrameCallback((_) {
columns ??= newColumns; setState(() {
_router ??= GlobalKey<VRouterState>(); _initialUrl = _router.currentState.url;
if (columns != newColumns) { columns = newColumns;
WidgetsBinding.instance.addPostFrameCallback((_) { _router = GlobalKey<VRouterState>();
setState(() {
_initialUrl = _router.currentState.url;
columns = newColumns;
_router = GlobalKey<VRouterState>();
});
}); });
} });
return VRouter( }
key: _router, return VRouter(
title: '${AppConfig.applicationName}', key: _router,
theme: theme, title: '${AppConfig.applicationName}',
darkTheme: darkTheme, theme: theme,
localizationsDelegates: L10n.localizationsDelegates, darkTheme: darkTheme,
supportedLocales: L10n.supportedLocales, localizationsDelegates: L10n.localizationsDelegates,
initialUrl: _initialUrl, supportedLocales: L10n.supportedLocales,
locale: kIsWeb initialUrl: _initialUrl,
? Locale(html.window.navigator.language.split('-').first) locale: kIsWeb
: null, ? Locale(html.window.navigator.language.split('-').first)
routes: AppRoutes(columns).routes, : null,
builder: (context, child) { routes: AppRoutes(columns).routes,
LoadingDialog.defaultTitle = L10n.of(context).loadingPleaseWait; builder: (context, child) {
LoadingDialog.defaultBackLabel = L10n.of(context).close; LoadingDialog.defaultTitle = L10n.of(context).loadingPleaseWait;
LoadingDialog.defaultOnError = LoadingDialog.defaultBackLabel = L10n.of(context).close;
(Object e) => e.toLocalizedString(context); LoadingDialog.defaultOnError =
return child; (Object e) => e.toLocalizedString(context);
}, return Matrix(
); key: _matrix,
}, context: context,
), router: _router,
testClient: widget.testClient,
child: child,
);
},
);
},
), ),
); );
} }

View file

@ -245,7 +245,10 @@ class ChatListController extends State<ChatList> {
} }
@override @override
Widget build(BuildContext context) => ChatListView(this); Widget build(BuildContext context) {
Matrix.of(context).navigatorContext = context;
return ChatListView(this);
}
} }
enum ChatListPopupMenuItemActions { enum ChatListPopupMenuItemActions {

View file

@ -65,5 +65,8 @@ class HomeserverPickerController extends State<HomeserverPicker> {
} }
@override @override
Widget build(BuildContext context) => HomeserverPickerView(this); Widget build(BuildContext context) {
Matrix.of(context).navigatorContext = context;
return HomeserverPickerView(this);
}
} }

View file

@ -153,7 +153,7 @@ class SignUpController extends State<SignUp> {
setState(() => loading = false); setState(() => loading = false);
VRouter.of(context).push( VRouter.of(context).push(
'/signup/password/${Uri.encodeComponent(preferredUsername)}/${Uri.encodeComponent(usernameController.text)}', '/signup/password/${Uri.encodeComponent(preferredUsername)}',
queryParameters: {'displayname': usernameController.text}, queryParameters: {'displayname': usernameController.text},
); );
} }

View file

@ -6,6 +6,7 @@ import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:vrouter/vrouter.dart';
class ChatPermissionsSettingsView extends StatelessWidget { class ChatPermissionsSettingsView extends StatelessWidget {
final ChatPermissionsSettingsController controller; final ChatPermissionsSettingsController controller;
@ -17,7 +18,11 @@ class ChatPermissionsSettingsView extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
leading: BackButton(), leading: IconButton(
icon: Icon(Icons.close_outlined),
onPressed: () =>
VRouter.of(context).push('/rooms/${controller.roomId}'),
),
title: Text(L10n.of(context).editChatPermissions), title: Text(L10n.of(context).editChatPermissions),
), ),
body: MaxWidthBody( body: MaxWidthBody(

View file

@ -7,6 +7,7 @@ import 'package:fluffychat/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:vrouter/vrouter.dart';
class InvitationSelectionView extends StatelessWidget { class InvitationSelectionView extends StatelessWidget {
final InvitationSelectionController controller; final InvitationSelectionController controller;
@ -20,7 +21,11 @@ class InvitationSelectionView extends StatelessWidget {
room.name?.isEmpty ?? false ? L10n.of(context).group : room.name; room.name?.isEmpty ?? false ? L10n.of(context).group : room.name;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
leading: BackButton(), leading: IconButton(
icon: Icon(Icons.close_outlined),
onPressed: () =>
VRouter.of(context).push('/rooms/${controller.roomId}'),
),
titleSpacing: 0, titleSpacing: 0,
title: DefaultAppBarSearchField( title: DefaultAppBarSearchField(
autofocus: true, autofocus: true,

View file

@ -14,32 +14,35 @@ class OnePageCard extends StatelessWidget {
return MediaQuery.of(context).size.width <= breakpoint || return MediaQuery.of(context).size.width <= breakpoint ||
MediaQuery.of(context).size.height <= breakpoint MediaQuery.of(context).size.height <= breakpoint
? child ? child
: Container( : Material(
decoration: BoxDecoration( color: Theme.of(context).backgroundColor,
color: Theme.of(context).backgroundColor, child: Container(
gradient: LinearGradient( decoration: BoxDecoration(
begin: Alignment.topRight, gradient: LinearGradient(
end: Alignment.bottomLeft, begin: Alignment.topRight,
stops: [ end: Alignment.bottomLeft,
0.1, stops: [
0.4, 0.1,
0.6, 0.4,
0.9, 0.6,
], 0.9,
colors: [ ],
Theme.of(context).secondaryHeaderColor.withAlpha(alpha), colors: [
Theme.of(context).primaryColor.withAlpha(alpha), Theme.of(context).secondaryHeaderColor.withAlpha(alpha),
Theme.of(context).accentColor.withAlpha(alpha), Theme.of(context).primaryColor.withAlpha(alpha),
Theme.of(context).backgroundColor.withAlpha(alpha), Theme.of(context).accentColor.withAlpha(alpha),
], Theme.of(context).backgroundColor.withAlpha(alpha),
],
),
), ),
padding: EdgeInsets.symmetric(
horizontal:
max((MediaQuery.of(context).size.width - 600) / 2, 12),
vertical:
max((MediaQuery.of(context).size.height - 800) / 2, 12),
),
child: SafeArea(child: Card(child: child)),
), ),
padding: EdgeInsets.symmetric(
horizontal:
max((MediaQuery.of(context).size.width - 600) / 2, 12),
vertical: max((MediaQuery.of(context).size.height - 800) / 2, 12),
),
child: SafeArea(child: Card(child: child)),
); );
} }
} }

View file

@ -18,8 +18,6 @@ import 'package:universal_html/html.dart' as html;
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:desktop_notifications/desktop_notifications.dart'; import 'package:desktop_notifications/desktop_notifications.dart';
import '../utils/beautify_string_extension.dart';
import '../utils/famedlysdk_store.dart'; import '../utils/famedlysdk_store.dart';
import '../pages/key_verification_dialog.dart'; import '../pages/key_verification_dialog.dart';
import '../utils/platform_infos.dart'; import '../utils/platform_infos.dart';
@ -59,8 +57,7 @@ class Matrix extends StatefulWidget {
class MatrixState extends State<Matrix> with WidgetsBindingObserver { class MatrixState extends State<Matrix> with WidgetsBindingObserver {
FluffyClient client; FluffyClient client;
Store store = Store(); Store store = Store();
@override BuildContext navigatorContext;
BuildContext get context => widget.context;
BackgroundPush _backgroundPush; BackgroundPush _backgroundPush;
@ -131,10 +128,10 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
case AuthenticationTypes.password: case AuthenticationTypes.password:
final input = cachedPassword ?? final input = cachedPassword ??
(await showTextInputDialog( (await showTextInputDialog(
context: context, context: navigatorContext,
title: L10n.of(context).pleaseEnterYourPassword, title: L10n.of(widget.context).pleaseEnterYourPassword,
okLabel: L10n.of(context).ok, okLabel: L10n.of(widget.context).ok,
cancelLabel: L10n.of(context).cancel, cancelLabel: L10n.of(widget.context).cancel,
textFields: [ textFields: [
DialogTextField( DialogTextField(
minLines: 1, minLines: 1,
@ -185,10 +182,10 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
); );
if (OkCancelResult.ok == if (OkCancelResult.ok ==
await showOkCancelAlertDialog( await showOkCancelAlertDialog(
message: L10n.of(context).pleaseFollowInstructionsOnWeb, message: L10n.of(widget.context).pleaseFollowInstructionsOnWeb,
context: context, context: navigatorContext,
okLabel: L10n.of(context).next, okLabel: L10n.of(widget.context).next,
cancelLabel: L10n.of(context).cancel, cancelLabel: L10n.of(widget.context).cancel,
)) { )) {
return uiaRequest.completeStage( return uiaRequest.completeStage(
AuthenticationData(session: uiaRequest.session), AuthenticationData(session: uiaRequest.session),
@ -211,9 +208,10 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
final room = client.getRoomById(roomId); final room = client.getRoomById(roomId);
if (room.notificationCount == 0) return; if (room.notificationCount == 0) return;
final event = Event.fromJson(eventUpdate.content, room); final event = Event.fromJson(eventUpdate.content, room);
final title = room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))); final title =
room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context)));
final body = event.getLocalizedBody( final body = event.getLocalizedBody(
MatrixLocals(L10n.of(context)), MatrixLocals(L10n.of(widget.context)),
withSenderNamePrefix: withSenderNamePrefix:
!room.isDirectChat || room.lastEvent.senderId == client.userID, !room.isDirectChat || room.lastEvent.senderId == client.userID,
); );
@ -276,33 +274,13 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
FlutterSecureStorage().read(key: SettingKeys.appLockKey).then((lock) { FlutterSecureStorage().read(key: SettingKeys.appLockKey).then((lock) {
if (lock?.isNotEmpty ?? false) { if (lock?.isNotEmpty ?? false) {
AppLock.of(context).enable(); AppLock.of(widget.context).enable();
AppLock.of(context).showLockScreen(); AppLock.of(widget.context).showLockScreen();
} }
}); });
}); });
} }
client = FluffyClient(); client = FluffyClient();
onRoomKeyRequestSub ??=
client.onRoomKeyRequest.stream.listen((RoomKeyRequest request) async {
final room = request.room;
if (request.sender != room.client.userID) {
return; // ignore share requests by others
}
final sender = room.getUserByMXIDSync(request.sender);
if (await showOkCancelAlertDialog(
context: context,
title: L10n.of(context).requestToReadOlderMessages,
message:
'${sender.id}\n\n${L10n.of(context).device}:\n${request.requestingDevice.deviceId}\n\n${L10n.of(context).publicKey}:\n${request.requestingDevice.ed25519Key.beautified}',
okLabel: L10n.of(context).verify,
cancelLabel: L10n.of(context).deny,
) ==
OkCancelResult.ok) {
await request.forwardKey();
}
});
onKeyVerificationRequestSub ??= client.onKeyVerificationRequest.stream onKeyVerificationRequestSub ??= client.onKeyVerificationRequest.stream
.listen((KeyVerification request) async { .listen((KeyVerification request) async {
var hidPopup = false; var hidPopup = false;
@ -310,22 +288,23 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
if (!hidPopup && if (!hidPopup &&
{KeyVerificationState.done, KeyVerificationState.error} {KeyVerificationState.done, KeyVerificationState.error}
.contains(request.state)) { .contains(request.state)) {
Navigator.of(context, rootNavigator: true).pop('dialog'); Navigator.of(navigatorContext).pop('dialog');
} }
hidPopup = true; hidPopup = true;
}; };
if (await showOkCancelAlertDialog( if (await showOkCancelAlertDialog(
context: context, context: navigatorContext,
title: L10n.of(context).newVerificationRequest, title: L10n.of(widget.context).newVerificationRequest,
message: L10n.of(context).askVerificationRequest(request.userId), message:
okLabel: L10n.of(context).ok, L10n.of(widget.context).askVerificationRequest(request.userId),
cancelLabel: L10n.of(context).cancel, okLabel: L10n.of(widget.context).ok,
cancelLabel: L10n.of(widget.context).cancel,
) == ) ==
OkCancelResult.ok) { OkCancelResult.ok) {
request.onUpdate = null; request.onUpdate = null;
hidPopup = true; hidPopup = true;
await request.acceptVerification(); await request.acceptVerification();
await KeyVerificationDialog(request: request).show(context); await KeyVerificationDialog(request: request).show(navigatorContext);
} else { } else {
request.onUpdate = null; request.onUpdate = null;
hidPopup = true; hidPopup = true;
@ -372,7 +351,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
} }
if (PlatformInfos.isMobile) { if (PlatformInfos.isMobile) {
_backgroundPush = BackgroundPush(client, context, widget.router); _backgroundPush = BackgroundPush(client, navigatorContext, widget.router);
} }
} }