mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-30 16:29:30 +01:00
Merge branch 'krille/apl' into 'main'
refactor: Use APL See merge request famedly/fluffychat!338
This commit is contained in:
commit
4b0f9fc8de
@ -1,52 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
enum FocusPage { FIRST, SECOND }
|
|
||||||
|
|
||||||
class AdaptivePageLayout extends StatelessWidget {
|
|
||||||
final Widget firstScaffold;
|
|
||||||
final Widget secondScaffold;
|
|
||||||
final FocusPage primaryPage;
|
|
||||||
final double minWidth;
|
|
||||||
|
|
||||||
static const double defaultMinWidth = 400;
|
|
||||||
static bool columnMode(BuildContext context) =>
|
|
||||||
MediaQuery.of(context).size.width > 2 * defaultMinWidth;
|
|
||||||
|
|
||||||
AdaptivePageLayout(
|
|
||||||
{this.firstScaffold,
|
|
||||||
this.secondScaffold,
|
|
||||||
this.primaryPage = FocusPage.FIRST,
|
|
||||||
this.minWidth = defaultMinWidth,
|
|
||||||
Key key})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return OrientationBuilder(builder: (context, orientation) {
|
|
||||||
if (orientation == Orientation.portrait || !columnMode(context)) {
|
|
||||||
if (primaryPage == FocusPage.FIRST) {
|
|
||||||
return firstScaffold;
|
|
||||||
} else {
|
|
||||||
return secondScaffold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
width: minWidth,
|
|
||||||
child: firstScaffold,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 1,
|
|
||||||
color: Theme.of(context).secondaryHeaderColor, //Color(0xFFE8E8E8),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
child: secondScaffold,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/chat_details.dart';
|
|
||||||
import 'package:fluffychat/views/chat_list.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:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
@ -95,9 +93,8 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
|
|||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context, future: () => widget.room.leave());
|
context: context, future: () => widget.room.leave());
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(context, ChatListView()),
|
.pushNamedAndRemoveAllOthers('/');
|
||||||
(Route r) => false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -117,12 +114,9 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
|
|||||||
startCallAction(context);
|
startCallAction(context);
|
||||||
break;
|
break;
|
||||||
case 'details':
|
case 'details':
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context).pushNamedAndRemoveAllOthers(
|
||||||
AppRoute.defaultRoute(
|
'/rooms/${widget.room.id}/details');
|
||||||
context,
|
|
||||||
ChatDetails(widget.room),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/archive.dart';
|
|
||||||
import 'package:fluffychat/views/discover_view.dart';
|
|
||||||
import 'package:fluffychat/views/new_group.dart';
|
|
||||||
import 'package:fluffychat/views/new_private_chat.dart';
|
|
||||||
import 'package:fluffychat/views/settings.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';
|
||||||
|
|
||||||
@ -13,15 +8,9 @@ import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|||||||
import 'matrix.dart';
|
import 'matrix.dart';
|
||||||
|
|
||||||
class DefaultDrawer extends StatelessWidget {
|
class DefaultDrawer extends StatelessWidget {
|
||||||
void _drawerTapAction(BuildContext context, Widget view) {
|
void _drawerTapAction(BuildContext context, String route) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
AdaptivePageLayout.of(context).pushNamedAndRemoveUntilIsFirst(route);
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context,
|
|
||||||
view,
|
|
||||||
),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setStatus(BuildContext context) async {
|
void _setStatus(BuildContext context) async {
|
||||||
@ -64,12 +53,12 @@ class DefaultDrawer extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.people_outline),
|
leading: Icon(Icons.people_outline),
|
||||||
title: Text(L10n.of(context).createNewGroup),
|
title: Text(L10n.of(context).createNewGroup),
|
||||||
onTap: () => _drawerTapAction(context, NewGroupView()),
|
onTap: () => _drawerTapAction(context, '/newgroup'),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.person_add_outlined),
|
leading: Icon(Icons.person_add_outlined),
|
||||||
title: Text(L10n.of(context).newPrivateChat),
|
title: Text(L10n.of(context).newPrivateChat),
|
||||||
onTap: () => _drawerTapAction(context, NewPrivateChatView()),
|
onTap: () => _drawerTapAction(context, '/newprivatechat'),
|
||||||
),
|
),
|
||||||
Divider(height: 1),
|
Divider(height: 1),
|
||||||
ListTile(
|
ListTile(
|
||||||
@ -77,7 +66,7 @@ class DefaultDrawer extends StatelessWidget {
|
|||||||
title: Text(L10n.of(context).archive),
|
title: Text(L10n.of(context).archive),
|
||||||
onTap: () => _drawerTapAction(
|
onTap: () => _drawerTapAction(
|
||||||
context,
|
context,
|
||||||
Archive(),
|
'/archive',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@ -85,7 +74,7 @@ class DefaultDrawer extends StatelessWidget {
|
|||||||
title: Text(L10n.of(context).discoverGroups),
|
title: Text(L10n.of(context).discoverGroups),
|
||||||
onTap: () => _drawerTapAction(
|
onTap: () => _drawerTapAction(
|
||||||
context,
|
context,
|
||||||
DiscoverView(),
|
'/discover',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(height: 1),
|
Divider(height: 1),
|
||||||
@ -94,7 +83,7 @@ class DefaultDrawer extends StatelessWidget {
|
|||||||
title: Text(L10n.of(context).settings),
|
title: Text(L10n.of(context).settings),
|
||||||
onTap: () => _drawerTapAction(
|
onTap: () => _drawerTapAction(
|
||||||
context,
|
context,
|
||||||
SettingsView(),
|
'/settings',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/chat_encryption_settings.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';
|
||||||
|
|
||||||
@ -23,12 +22,8 @@ class _EncryptionButtonState extends State<EncryptionButton> {
|
|||||||
|
|
||||||
void _enableEncryptionAction() async {
|
void _enableEncryptionAction() async {
|
||||||
if (widget.room.encrypted) {
|
if (widget.room.encrypted) {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamed('/rooms/${widget.room.id}/encryption');
|
||||||
context,
|
|
||||||
ChatEncryptionSettingsView(widget.room.id),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!widget.room.client.encryptionEnabled) {
|
if (!widget.room.client.encryptionEnabled) {
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:circular_check_box/circular_check_box.dart';
|
import 'package:circular_check_box/circular_check_box.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/config/themes.dart';
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:fluffychat/utils/event_extension.dart';
|
import 'package:fluffychat/utils/event_extension.dart';
|
||||||
import 'package:fluffychat/utils/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/room_status_extension.dart';
|
import 'package:fluffychat/utils/room_status_extension.dart';
|
||||||
import 'package:fluffychat/views/chat.dart';
|
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.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:pedantic/pedantic.dart';
|
import 'package:pedantic/pedantic.dart';
|
||||||
|
|
||||||
import '../../utils/app_route.dart';
|
|
||||||
import '../../utils/date_time_extension.dart';
|
import '../../utils/date_time_extension.dart';
|
||||||
import '../../views/chat.dart';
|
|
||||||
import '../avatar.dart';
|
import '../avatar.dart';
|
||||||
import '../dialogs/send_file_dialog.dart';
|
import '../dialogs/send_file_dialog.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
@ -102,11 +100,8 @@ class ChatListItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
Matrix.of(context).shareContent = null;
|
Matrix.of(context).shareContent = null;
|
||||||
}
|
}
|
||||||
await Navigator.pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
context,
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${room.id}');
|
||||||
AppRoute.defaultRoute(context, ChatView(room.id)),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/message_content.dart';
|
import 'package:fluffychat/components/message_content.dart';
|
||||||
import 'package:fluffychat/components/reply_content.dart';
|
import 'package:fluffychat/components/reply_content.dart';
|
||||||
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||||
import 'package:fluffychat/utils/event_extension.dart';
|
import 'package:fluffychat/utils/event_extension.dart';
|
||||||
import 'package:fluffychat/utils/string_color.dart';
|
import 'package:fluffychat/utils/string_color.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../adaptive_page_layout.dart';
|
|
||||||
import '../avatar.dart';
|
import '../avatar.dart';
|
||||||
import '../matrix.dart';
|
import '../matrix.dart';
|
||||||
import '../message_reactions.dart';
|
import '../message_reactions.dart';
|
||||||
@ -88,8 +88,7 @@ class Message extends StatelessWidget {
|
|||||||
color: color,
|
color: color,
|
||||||
borderRadius: BorderRadius.circular(radius),
|
borderRadius: BorderRadius.circular(radius),
|
||||||
),
|
),
|
||||||
constraints:
|
constraints: BoxConstraints(maxWidth: FluffyThemes.columnWidth),
|
||||||
BoxConstraints(maxWidth: AdaptivePageLayout.defaultMinWidth),
|
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Column(
|
Column(
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.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 '../../utils/app_route.dart';
|
|
||||||
import '../../views/chat.dart';
|
|
||||||
import '../avatar.dart';
|
import '../avatar.dart';
|
||||||
import '../matrix.dart';
|
import '../matrix.dart';
|
||||||
|
|
||||||
@ -19,12 +18,8 @@ class PublicRoomListItem extends StatelessWidget {
|
|||||||
future: () => _joinRoomAndWait(context),
|
future: () => _joinRoomAndWait(context),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamed('/rooms/${success.result}');
|
||||||
context,
|
|
||||||
ChatView(success.result),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,13 @@ import 'dart:io';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/encryption.dart';
|
import 'package:famedlysdk/encryption.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/firebase_controller.dart';
|
import 'package:fluffychat/utils/firebase_controller.dart';
|
||||||
import 'package:fluffychat/utils/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
import 'package:fluffychat/utils/sentry_controller.dart';
|
import 'package:fluffychat/utils/sentry_controller.dart';
|
||||||
import 'package:fluffychat/views/settings_3pid.dart';
|
|
||||||
import 'package:flushbar/flushbar.dart';
|
import 'package:flushbar/flushbar.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -38,7 +37,16 @@ class Matrix extends StatefulWidget {
|
|||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
Matrix({this.child, Key key}) : super(key: key);
|
final GlobalKey<AdaptivePageLayoutState> apl;
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
Matrix({
|
||||||
|
this.child,
|
||||||
|
@required this.apl,
|
||||||
|
@required this.context,
|
||||||
|
Key key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MatrixState createState() => MatrixState();
|
MatrixState createState() => MatrixState();
|
||||||
@ -52,7 +60,7 @@ class MatrixState extends State<Matrix> {
|
|||||||
Client client;
|
Client client;
|
||||||
Store store = Store();
|
Store store = Store();
|
||||||
@override
|
@override
|
||||||
BuildContext context;
|
BuildContext get context => widget.context;
|
||||||
|
|
||||||
Map<String, dynamic> get shareContent => _shareContent;
|
Map<String, dynamic> get shareContent => _shareContent;
|
||||||
set shareContent(Map<String, dynamic> content) {
|
set shareContent(Map<String, dynamic> content) {
|
||||||
@ -76,29 +84,16 @@ class MatrixState extends State<Matrix> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _initWithStore() async {
|
void _initWithStore() async {
|
||||||
var initLoginState = client.onLoginStateChanged.stream.first;
|
|
||||||
try {
|
try {
|
||||||
client.init();
|
client.init();
|
||||||
|
|
||||||
final firstLoginState = await initLoginState;
|
|
||||||
if (firstLoginState == LoginState.logged) {
|
|
||||||
if (PlatformInfos.isMobile) {
|
|
||||||
await FirebaseController.setupFirebase(
|
|
||||||
this,
|
|
||||||
clientName,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final storeItem = await store.getItem(SettingKeys.showNoPid);
|
final storeItem = await store.getItem(SettingKeys.showNoPid);
|
||||||
final configOptionMissing = storeItem == null || storeItem.isEmpty;
|
final configOptionMissing = storeItem == null || storeItem.isEmpty;
|
||||||
if (configOptionMissing || (!configOptionMissing && storeItem == '1')) {
|
if (configOptionMissing || (!configOptionMissing && storeItem == '1')) {
|
||||||
if (configOptionMissing) {
|
if (configOptionMissing) {
|
||||||
await store.setItem(SettingKeys.showNoPid, '0');
|
await store.setItem(SettingKeys.showNoPid, '0');
|
||||||
}
|
}
|
||||||
await Matrix.of(context)
|
await client.requestThirdPartyIdentifiers().then((l) {
|
||||||
.client
|
|
||||||
.requestThirdPartyIdentifiers()
|
|
||||||
.then((l) {
|
|
||||||
if (l.isEmpty) {
|
if (l.isEmpty) {
|
||||||
Flushbar(
|
Flushbar(
|
||||||
title: L10n.of(context).warning,
|
title: L10n.of(context).warning,
|
||||||
@ -110,12 +105,8 @@ class MatrixState extends State<Matrix> {
|
|||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
),
|
),
|
||||||
child: Text(L10n.of(context).edit),
|
child: Text(L10n.of(context).edit),
|
||||||
onPressed: () => Navigator.of(context).push(
|
onPressed: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/3pid'),
|
||||||
context,
|
|
||||||
Settings3PidView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
flushbarStyle: FlushbarStyle.FLOATING,
|
flushbarStyle: FlushbarStyle.FLOATING,
|
||||||
).show(context);
|
).show(context);
|
||||||
@ -133,6 +124,7 @@ class MatrixState extends State<Matrix> {
|
|||||||
StreamSubscription onKeyVerificationRequestSub;
|
StreamSubscription onKeyVerificationRequestSub;
|
||||||
StreamSubscription onJitsiCallSub;
|
StreamSubscription onJitsiCallSub;
|
||||||
StreamSubscription onNotification;
|
StreamSubscription onNotification;
|
||||||
|
StreamSubscription<LoginState> onLoginStateChanged;
|
||||||
StreamSubscription<UiaRequest> onUiaRequest;
|
StreamSubscription<UiaRequest> onUiaRequest;
|
||||||
StreamSubscription<html.Event> onFocusSub;
|
StreamSubscription<html.Event> onFocusSub;
|
||||||
StreamSubscription<html.Event> onBlurSub;
|
StreamSubscription<html.Event> onBlurSub;
|
||||||
@ -301,6 +293,8 @@ class MatrixState extends State<Matrix> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoginState loginState;
|
||||||
|
|
||||||
void initMatrix() {
|
void initMatrix() {
|
||||||
clientName =
|
clientName =
|
||||||
'${AppConfig.applicationName} ${kIsWeb ? 'Web' : Platform.operatingSystem}';
|
'${AppConfig.applicationName} ${kIsWeb ? 'Web' : Platform.operatingSystem}';
|
||||||
@ -380,6 +374,19 @@ class MatrixState extends State<Matrix> {
|
|||||||
onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true);
|
onFocusSub = html.window.onFocus.listen((_) => webHasFocus = true);
|
||||||
onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false);
|
onBlurSub = html.window.onBlur.listen((_) => webHasFocus = false);
|
||||||
}
|
}
|
||||||
|
onLoginStateChanged ??= client.onLoginStateChanged.stream.listen((state) {
|
||||||
|
if (loginState != state) {
|
||||||
|
loginState = state;
|
||||||
|
widget.apl.currentState.pushNamedAndRemoveAllOthers('/');
|
||||||
|
if (loginState == LoginState.logged) {
|
||||||
|
FirebaseController.context = context;
|
||||||
|
FirebaseController.setupFirebase(
|
||||||
|
this,
|
||||||
|
clientName,
|
||||||
|
).catchError(SentryController.captureException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
onUiaRequest ??= client.onUiaRequest.stream.listen(_onUiaRequest);
|
onUiaRequest ??= client.onUiaRequest.stream.listen(_onUiaRequest);
|
||||||
if (kIsWeb || Platform.isLinux) {
|
if (kIsWeb || Platform.isLinux) {
|
||||||
client.onSync.stream.first.then((s) {
|
client.onSync.stream.first.then((s) {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
|
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||||
import 'package:fluffychat/views/chat.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'content_banner.dart';
|
import 'content_banner.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
@ -15,7 +14,6 @@ import '../utils/presence_extension.dart';
|
|||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'matrix.dart';
|
import 'matrix.dart';
|
||||||
import 'dialogs/key_verification_dialog.dart';
|
import 'dialogs/key_verification_dialog.dart';
|
||||||
import '../utils/app_route.dart';
|
|
||||||
|
|
||||||
class UserBottomSheet extends StatelessWidget {
|
class UserBottomSheet extends StatelessWidget {
|
||||||
final User user;
|
final User user;
|
||||||
@ -76,12 +74,8 @@ class UserBottomSheet extends StatelessWidget {
|
|||||||
break;
|
break;
|
||||||
case 'message':
|
case 'message':
|
||||||
final roomId = await user.startDirectChat();
|
final roomId = await user.startDirectChat();
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
||||||
context,
|
|
||||||
ChatView(roomId),
|
|
||||||
),
|
|
||||||
(Route r) => r.isFirst);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,8 +155,8 @@ class UserBottomSheet extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: min(MediaQuery.of(context).size.width,
|
width: min(
|
||||||
AdaptivePageLayout.defaultMinWidth * 1.5),
|
MediaQuery.of(context).size.width, FluffyThemes.columnWidth * 1.5),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Material(
|
child: Material(
|
||||||
elevation: 4,
|
elevation: 4,
|
||||||
|
228
lib/config/routes.dart
Normal file
228
lib/config/routes.dart
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
|
import 'package:fluffychat/views/archive.dart';
|
||||||
|
import 'package:fluffychat/views/auth_web_view.dart';
|
||||||
|
import 'package:fluffychat/views/chat.dart';
|
||||||
|
import 'package:fluffychat/views/chat_details.dart';
|
||||||
|
import 'package:fluffychat/views/chat_encryption_settings.dart';
|
||||||
|
import 'package:fluffychat/views/chat_list.dart';
|
||||||
|
import 'package:fluffychat/views/chat_permissions_settings.dart';
|
||||||
|
import 'package:fluffychat/views/discover_view.dart';
|
||||||
|
import 'package:fluffychat/views/empty_page.dart';
|
||||||
|
import 'package:fluffychat/views/homeserver_picker.dart';
|
||||||
|
import 'package:fluffychat/views/invitation_selection.dart';
|
||||||
|
import 'package:fluffychat/views/loading_view.dart';
|
||||||
|
import 'package:fluffychat/views/log_view.dart';
|
||||||
|
import 'package:fluffychat/views/login.dart';
|
||||||
|
import 'package:fluffychat/views/new_group.dart';
|
||||||
|
import 'package:fluffychat/views/new_private_chat.dart';
|
||||||
|
import 'package:fluffychat/views/settings.dart';
|
||||||
|
import 'package:fluffychat/views/settings_3pid.dart';
|
||||||
|
import 'package:fluffychat/views/settings_devices.dart';
|
||||||
|
import 'package:fluffychat/views/settings_emotes.dart';
|
||||||
|
import 'package:fluffychat/views/settings_ignore_list.dart';
|
||||||
|
import 'package:fluffychat/views/settings_multiple_emotes.dart';
|
||||||
|
import 'package:fluffychat/views/settings_notifications.dart';
|
||||||
|
import 'package:fluffychat/views/settings_style.dart';
|
||||||
|
import 'package:fluffychat/views/sign_up.dart';
|
||||||
|
import 'package:fluffychat/views/sign_up_password.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FluffyRoutes {
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
const FluffyRoutes(this.context);
|
||||||
|
|
||||||
|
ViewData onGenerateRoute(RouteSettings settings) {
|
||||||
|
final parts = settings.name.split('/');
|
||||||
|
Logs().v(settings.name);
|
||||||
|
|
||||||
|
// Routes if the app is loading
|
||||||
|
if (Matrix.of(context).loginState == null) {
|
||||||
|
return ViewData(mainView: (_) => LoadingView());
|
||||||
|
// Routes if user is NOT logged in
|
||||||
|
} else if (Matrix.of(context).loginState == LoginState.loggedOut) {
|
||||||
|
switch (parts[1]) {
|
||||||
|
case '':
|
||||||
|
return ViewData(mainView: (_) => HomeserverPicker());
|
||||||
|
case 'login':
|
||||||
|
return ViewData(mainView: (_) => Login());
|
||||||
|
case 'signup':
|
||||||
|
if (parts.length == 5 && parts[2] == 'password') {
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => SignUpPassword(
|
||||||
|
parts[3],
|
||||||
|
displayname: parts[4],
|
||||||
|
avatar: settings.arguments,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ViewData(mainView: (_) => SignUp());
|
||||||
|
case 'authwebview':
|
||||||
|
if (parts.length == 4) {
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => AuthWebView(
|
||||||
|
parts[2],
|
||||||
|
Uri.decodeComponent(parts[3]),
|
||||||
|
settings.arguments,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Routes IF user is logged in
|
||||||
|
else {
|
||||||
|
switch (parts[1]) {
|
||||||
|
case '':
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => ChatList(),
|
||||||
|
emptyView: (_) => EmptyPage(),
|
||||||
|
);
|
||||||
|
case 'rooms':
|
||||||
|
if (parts.length == 3) {
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
);
|
||||||
|
} else if (parts.length == 4) {
|
||||||
|
final roomId = parts[2];
|
||||||
|
final action = parts[3];
|
||||||
|
switch (action) {
|
||||||
|
case 'details':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
rightView: (_) => ChatDetails(roomId),
|
||||||
|
);
|
||||||
|
case 'encryption':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
rightView: (_) => ChatEncryptionSettings(roomId),
|
||||||
|
);
|
||||||
|
case 'permissions':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
rightView: (_) => ChatPermissionsSettings(roomId),
|
||||||
|
);
|
||||||
|
case 'invite':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
rightView: (_) => InvitationSelection(roomId),
|
||||||
|
);
|
||||||
|
case 'emotes':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => Chat(parts[2]),
|
||||||
|
rightView: (_) => MultipleEmotesSettings(roomId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => ChatList(),
|
||||||
|
emptyView: (_) => EmptyPage(),
|
||||||
|
);
|
||||||
|
case 'archive':
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => Archive(),
|
||||||
|
emptyView: (_) => Chat(parts[2]),
|
||||||
|
);
|
||||||
|
case 'discover':
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) =>
|
||||||
|
DiscoverPage(alias: parts.length == 3 ? parts[2] : null),
|
||||||
|
emptyView: (_) => EmptyPage(),
|
||||||
|
);
|
||||||
|
case 'logs':
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => LogViewer(),
|
||||||
|
);
|
||||||
|
case 'newgroup':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => NewGroup(),
|
||||||
|
);
|
||||||
|
case 'newprivatechat':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => ChatList(),
|
||||||
|
mainView: (_) => NewPrivateChat(),
|
||||||
|
);
|
||||||
|
case 'settings':
|
||||||
|
if (parts.length == 3) {
|
||||||
|
final action = parts[2];
|
||||||
|
switch (action) {
|
||||||
|
case '3pid':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => Settings3Pid(),
|
||||||
|
);
|
||||||
|
case 'devices':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => DevicesSettings(),
|
||||||
|
);
|
||||||
|
case 'emotes':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => EmotesSettings(room: settings.arguments),
|
||||||
|
);
|
||||||
|
case 'ignore':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => SettingsIgnoreList(),
|
||||||
|
);
|
||||||
|
case 'notifications':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => SettingsNotifications(),
|
||||||
|
);
|
||||||
|
case 'style':
|
||||||
|
return ViewData(
|
||||||
|
leftView: (_) => Settings(),
|
||||||
|
mainView: (_) => SettingsStyle(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => Settings(),
|
||||||
|
emptyView: (_) => EmptyPage(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If route cant be found:
|
||||||
|
return ViewData(
|
||||||
|
mainView: (_) => Center(
|
||||||
|
child: Text('Route "${settings.name}" not found...'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsDevices {}
|
||||||
|
|
||||||
|
class FadeRoute extends PageRouteBuilder {
|
||||||
|
final Widget page;
|
||||||
|
FadeRoute({this.page})
|
||||||
|
: super(
|
||||||
|
pageBuilder: (
|
||||||
|
BuildContext context,
|
||||||
|
Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
) =>
|
||||||
|
page,
|
||||||
|
transitionsBuilder: (
|
||||||
|
BuildContext context,
|
||||||
|
Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
Widget child,
|
||||||
|
) =>
|
||||||
|
FadeTransition(
|
||||||
|
opacity: animation,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
abstract class FluffyThemes {
|
abstract class FluffyThemes {
|
||||||
|
static const double columnWidth = 360.0;
|
||||||
static ThemeData light = ThemeData(
|
static ThemeData light = ThemeData(
|
||||||
primaryColorDark: Colors.white,
|
primaryColorDark: Colors.white,
|
||||||
primaryColorLight: Color(0xff121212),
|
primaryColorLight: Color(0xff121212),
|
||||||
|
@ -2,22 +2,19 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_theme/adaptive_theme.dart';
|
import 'package:adaptive_theme/adaptive_theme.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
|
import 'package:fluffychat/config/routes.dart';
|
||||||
import 'package:fluffychat/utils/sentry_controller.dart';
|
import 'package:fluffychat/utils/sentry_controller.dart';
|
||||||
import 'package:fluffychat/views/homeserver_picker.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
|
||||||
import 'package:flutter/foundation.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:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|
||||||
import 'package:universal_html/prefer_universal/html.dart' as html;
|
import 'package:universal_html/prefer_universal/html.dart' as html;
|
||||||
|
|
||||||
import 'components/matrix.dart';
|
import 'components/matrix.dart';
|
||||||
import 'config/themes.dart';
|
import 'config/themes.dart';
|
||||||
import 'utils/localized_exception_extension.dart';
|
|
||||||
import 'app_config.dart';
|
import 'app_config.dart';
|
||||||
import 'views/chat_list.dart';
|
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
SystemChrome.setSystemUIOverlayStyle(
|
SystemChrome.setSystemUIOverlayStyle(
|
||||||
@ -31,51 +28,38 @@ void main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class App extends StatelessWidget {
|
class App extends StatelessWidget {
|
||||||
|
final GlobalKey<AdaptivePageLayoutState> _apl =
|
||||||
|
GlobalKey<AdaptivePageLayoutState>();
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Matrix(
|
return AdaptiveTheme(
|
||||||
child: Builder(
|
light: FluffyThemes.light,
|
||||||
builder: (BuildContext context) => AdaptiveTheme(
|
dark: FluffyThemes.dark,
|
||||||
light: FluffyThemes.light,
|
initial: AdaptiveThemeMode.system,
|
||||||
dark: FluffyThemes.dark,
|
builder: (theme, darkTheme) => MaterialApp(
|
||||||
initial: AdaptiveThemeMode.system,
|
title: '${AppConfig.applicationName}',
|
||||||
builder: (theme, darkTheme) => MaterialApp(
|
theme: theme,
|
||||||
title: '${AppConfig.applicationName}',
|
darkTheme: darkTheme,
|
||||||
theme: theme,
|
localizationsDelegates: L10n.localizationsDelegates,
|
||||||
darkTheme: darkTheme,
|
supportedLocales: L10n.supportedLocales,
|
||||||
localizationsDelegates: L10n.localizationsDelegates,
|
locale: kIsWeb
|
||||||
supportedLocales: L10n.supportedLocales,
|
? Locale(html.window.navigator.language.split('-').first)
|
||||||
locale: kIsWeb
|
: null,
|
||||||
? Locale(html.window.navigator.language.split('-').first)
|
home: Builder(
|
||||||
: null,
|
builder: (context) => Matrix(
|
||||||
home: FutureBuilder<LoginState>(
|
context: context,
|
||||||
future:
|
apl: _apl,
|
||||||
Matrix.of(context).client.onLoginStateChanged.stream.first,
|
child: Builder(
|
||||||
builder: (context, snapshot) {
|
builder: (context) => AdaptivePageLayout(
|
||||||
LoadingDialog.defaultTitle = L10n.of(context).loadingPleaseWait;
|
key: _apl,
|
||||||
LoadingDialog.defaultBackLabel = L10n.of(context).close;
|
onGenerateRoute: FluffyRoutes(context).onGenerateRoute,
|
||||||
LoadingDialog.defaultOnError =
|
dividerColor: Theme.of(context).dividerColor,
|
||||||
(Object e) => e.toLocalizedString(context);
|
columnWidth: FluffyThemes.columnWidth,
|
||||||
if (snapshot.hasError) {
|
routeBuilder: (builder, settings) =>
|
||||||
WidgetsBinding.instance
|
_apl.currentState.columnMode(context)
|
||||||
.addPostFrameCallback((_) => FlushbarHelper.createError(
|
? FadeRoute(page: builder(context))
|
||||||
title: L10n.of(context).oopsSomethingWentWrong,
|
: CupertinoPageRoute(builder: builder),
|
||||||
message: snapshot.error.toString(),
|
),
|
||||||
).show(context));
|
|
||||||
return HomeserverPicker();
|
|
||||||
}
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return Scaffold(
|
|
||||||
body: Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (Matrix.of(context).client.isLogged()) {
|
|
||||||
return ChatListView();
|
|
||||||
}
|
|
||||||
return HomeserverPicker();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AppRoute extends PageRouteBuilder {
|
class AppRoute extends PageRouteBuilder {
|
||||||
static Route defaultRoute(BuildContext context, Widget page) {
|
static Route defaultRoute(BuildContext context, Widget page) {
|
||||||
return context != null && !AdaptivePageLayout.columnMode(context)
|
return context != null &&
|
||||||
|
!AdaptivePageLayout.of(context).columnMode(context)
|
||||||
? CupertinoPageRoute(
|
? CupertinoPageRoute(
|
||||||
builder: (BuildContext context) => page,
|
builder: (BuildContext context) => page,
|
||||||
)
|
)
|
||||||
|
@ -7,8 +7,6 @@ import 'package:flushbar/flushbar_helper.dart';
|
|||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/chat.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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';
|
||||||
@ -112,12 +110,8 @@ abstract class FirebaseController {
|
|||||||
roomId = (message['data'] ?? message)['room_id'];
|
roomId = (message['data'] ?? message)['room_id'];
|
||||||
}
|
}
|
||||||
if (roomId?.isEmpty ?? true) throw ('Bad roomId');
|
if (roomId?.isEmpty ?? true) throw ('Bad roomId');
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
await matrix.widget.apl.currentState
|
||||||
AppRoute.defaultRoute(
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
||||||
context,
|
|
||||||
ChatView(roomId),
|
|
||||||
),
|
|
||||||
(r) => r.isFirst);
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
await FlushbarHelper.createError(message: 'Failed to open chat...')
|
await FlushbarHelper.createError(message: 'Failed to open chat...')
|
||||||
.show(context);
|
.show(context);
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/app_config.dart';
|
import 'package:fluffychat/app_config.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/chat.dart';
|
|
||||||
import 'package:fluffychat/views/discover_view.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
@ -74,12 +72,8 @@ class UrlLauncher {
|
|||||||
}
|
}
|
||||||
if (room != null) {
|
if (room != null) {
|
||||||
// we have the room, so....just open it!
|
// we have the room, so....just open it!
|
||||||
await Navigator.pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
context,
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${room.id}/$event');
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context, ChatView(room.id, scrollToEventId: event)),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (roomIdOrAlias.sigil == '!') {
|
if (roomIdOrAlias.sigil == '!') {
|
||||||
@ -101,21 +95,12 @@ class UrlLauncher {
|
|||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => Future.delayed(const Duration(seconds: 2)));
|
future: () => Future.delayed(const Duration(seconds: 2)));
|
||||||
await Navigator.pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context).pushNamedAndRemoveUntilIsFirst(
|
||||||
context,
|
'/rooms/${response.result}/$event');
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context, ChatView(response.result, scrollToEventId: event)),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamedAndRemoveUntilIsFirst('/discover/${roomIdOrAlias}');
|
||||||
context,
|
|
||||||
DiscoverView(alias: roomIdOrAlias),
|
|
||||||
),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
||||||
final user = User(
|
final user = User(
|
||||||
@ -124,11 +109,9 @@ class UrlLauncher {
|
|||||||
);
|
);
|
||||||
var roomId = matrix.client.getDirectChatFromUserId(user.id);
|
var roomId = matrix.client.getDirectChatFromUserId(user.id);
|
||||||
if (roomId != null) {
|
if (roomId != null) {
|
||||||
await Navigator.pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
context,
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
||||||
AppRoute.defaultRoute(context, ChatView(roomId)),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,14 +125,10 @@ class UrlLauncher {
|
|||||||
future: () => user.startDirectChat(),
|
future: () => user.startDirectChat(),
|
||||||
))
|
))
|
||||||
.result;
|
.result;
|
||||||
Navigator.of(context).pop();
|
|
||||||
|
|
||||||
if (roomId != null) {
|
if (roomId != null) {
|
||||||
await Navigator.pushAndRemoveUntil(
|
await AdaptivePageLayout.of(context)
|
||||||
context,
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
||||||
AppRoute.defaultRoute(context, ChatView(roomId)),
|
|
||||||
(r) => r.isFirst,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/list_items/chat_list_item.dart';
|
import 'package:fluffychat/components/list_items/chat_list_item.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -35,36 +34,28 @@ class _ArchiveState extends State<Archive> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AdaptivePageLayout(
|
return Scaffold(
|
||||||
firstScaffold: Scaffold(
|
appBar: AppBar(
|
||||||
appBar: AppBar(
|
title: Text(L10n.of(context).archive),
|
||||||
title: Text(L10n.of(context).archive),
|
elevation: _scrolledToTop ? 0 : null,
|
||||||
elevation: _scrolledToTop ? 0 : null,
|
|
||||||
),
|
|
||||||
body: FutureBuilder<List<Room>>(
|
|
||||||
future: getArchive(context),
|
|
||||||
builder: (BuildContext context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return Center(child: CircularProgressIndicator());
|
|
||||||
} else {
|
|
||||||
archive = snapshot.data;
|
|
||||||
return ListView.builder(
|
|
||||||
controller: _scrollController,
|
|
||||||
itemCount: archive.length,
|
|
||||||
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
|
||||||
archive[i],
|
|
||||||
onForget: () => setState(() => archive.removeAt(i))),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
secondScaffold: Scaffold(
|
body: FutureBuilder<List<Room>>(
|
||||||
body: Center(
|
future: getArchive(context),
|
||||||
child: Image.asset('assets/logo.png', width: 100, height: 100),
|
builder: (BuildContext context, snapshot) {
|
||||||
),
|
if (!snapshot.hasData) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
} else {
|
||||||
|
archive = snapshot.data;
|
||||||
|
return ListView.builder(
|
||||||
|
controller: _scrollController,
|
||||||
|
itemCount: archive.length,
|
||||||
|
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
||||||
|
archive[i],
|
||||||
|
onForget: () => setState(() => archive.removeAt(i))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
primaryPage: FocusPage.FIRST,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -23,7 +24,7 @@ class AuthWebView extends StatelessWidget {
|
|||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
icon: Icon(Icons.close),
|
icon: Icon(Icons.close),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
AdaptivePageLayout.of(context).pop();
|
||||||
onAuthDone();
|
onAuthDone();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -3,14 +3,15 @@ import 'dart:io';
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:emoji_picker/emoji_picker.dart';
|
import 'package:emoji_picker/emoji_picker.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
||||||
import 'package:fluffychat/components/connection_status_header.dart';
|
import 'package:fluffychat/components/connection_status_header.dart';
|
||||||
import 'package:fluffychat/components/dialogs/recording_dialog.dart';
|
import 'package:fluffychat/components/dialogs/recording_dialog.dart';
|
||||||
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/encryption_button.dart';
|
import 'package:fluffychat/components/encryption_button.dart';
|
||||||
@ -19,7 +20,6 @@ import 'package:fluffychat/components/matrix.dart';
|
|||||||
import 'package:fluffychat/components/reply_content.dart';
|
import 'package:fluffychat/components/reply_content.dart';
|
||||||
import 'package:fluffychat/components/user_bottom_sheet.dart';
|
import 'package:fluffychat/components/user_bottom_sheet.dart';
|
||||||
import 'package:fluffychat/config/app_emojis.dart';
|
import 'package:fluffychat/config/app_emojis.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
import 'package:fluffychat/utils/room_status_extension.dart';
|
import 'package:fluffychat/utils/room_status_extension.dart';
|
||||||
@ -38,39 +38,19 @@ import '../components/dialogs/send_file_dialog.dart';
|
|||||||
import '../components/input_bar.dart';
|
import '../components/input_bar.dart';
|
||||||
import '../utils/filtered_timeline_extension.dart';
|
import '../utils/filtered_timeline_extension.dart';
|
||||||
import '../utils/matrix_file_extension.dart';
|
import '../utils/matrix_file_extension.dart';
|
||||||
import 'chat_details.dart';
|
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class ChatView extends StatelessWidget {
|
class Chat extends StatefulWidget {
|
||||||
final String id;
|
final String id;
|
||||||
final String scrollToEventId;
|
final String scrollToEventId;
|
||||||
|
|
||||||
const ChatView(this.id, {Key key, this.scrollToEventId}) : super(key: key);
|
Chat(this.id, {Key key, this.scrollToEventId})
|
||||||
|
: super(key: key ?? Key('chatroom-$id'));
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// TODO: implement build
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(
|
|
||||||
activeChat: id,
|
|
||||||
),
|
|
||||||
secondScaffold: _Chat(id, scrollToEventId: scrollToEventId),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Chat extends StatefulWidget {
|
|
||||||
final String id;
|
|
||||||
final String scrollToEventId;
|
|
||||||
|
|
||||||
const _Chat(this.id, {Key key, this.scrollToEventId}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ChatState createState() => _ChatState();
|
_ChatState createState() => _ChatState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ChatState extends State<_Chat> {
|
class _ChatState extends State<Chat> {
|
||||||
Room room;
|
Room room;
|
||||||
|
|
||||||
Timeline timeline;
|
Timeline timeline;
|
||||||
@ -343,7 +323,7 @@ class _ChatState extends State<_Chat> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
setState(() => selectedEvents.clear());
|
setState(() => selectedEvents.clear());
|
||||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
AdaptivePageLayout.of(context).popUntilIsFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendAgainAction(Timeline timeline) {
|
void sendAgainAction(Timeline timeline) {
|
||||||
@ -509,12 +489,8 @@ class _ChatState extends State<_Chat> {
|
|||||||
'${room.directChatMatrixID} ',
|
'${room.directChatMatrixID} ',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: () => Navigator.of(context).push(
|
: () => AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamed('/rooms/${room.id}/details'),
|
||||||
context,
|
|
||||||
ChatDetails(room),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(
|
title: Text(
|
||||||
room.getLocalizedDisplayname(
|
room.getLocalizedDisplayname(
|
||||||
MatrixLocals(L10n.of(context))),
|
MatrixLocals(L10n.of(context))),
|
||||||
@ -643,8 +619,7 @@ class _ChatState extends State<_Chat> {
|
|||||||
horizontal: max(
|
horizontal: max(
|
||||||
0,
|
0,
|
||||||
(MediaQuery.of(context).size.width -
|
(MediaQuery.of(context).size.width -
|
||||||
AdaptivePageLayout.defaultMinWidth *
|
FluffyThemes.columnWidth * 3.5) /
|
||||||
3.5) /
|
|
||||||
2),
|
2),
|
||||||
),
|
),
|
||||||
reverse: true,
|
reverse: true,
|
||||||
|
@ -1,40 +1,36 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:fluffychat/app_config.dart';
|
import 'package:fluffychat/app_config.dart';
|
||||||
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||||
import 'package:fluffychat/views/chat_permissions_settings.dart';
|
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
||||||
import 'package:fluffychat/components/content_banner.dart';
|
import 'package:fluffychat/components/content_banner.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/list_items/participant_list_item.dart';
|
import 'package:fluffychat/components/list_items/participant_list_item.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
import 'package:fluffychat/views/chat_list.dart';
|
|
||||||
import 'package:fluffychat/views/invitation_selection.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:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:matrix_link_text/link_text.dart';
|
import 'package:matrix_link_text/link_text.dart';
|
||||||
|
|
||||||
import './settings_emotes.dart';
|
|
||||||
import './settings_multiple_emotes.dart';
|
|
||||||
import '../utils/url_launcher.dart';
|
import '../utils/url_launcher.dart';
|
||||||
|
|
||||||
class ChatDetails extends StatefulWidget {
|
class ChatDetails extends StatefulWidget {
|
||||||
final Room room;
|
final String roomId;
|
||||||
|
|
||||||
const ChatDetails(this.room);
|
const ChatDetails(this.roomId);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ChatDetailsState createState() => _ChatDetailsState();
|
_ChatDetailsState createState() => _ChatDetailsState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ChatDetailsState extends State<ChatDetails> {
|
class _ChatDetailsState extends State<ChatDetails> {
|
||||||
|
Room room;
|
||||||
List<User> members;
|
List<User> members;
|
||||||
void setDisplaynameAction(BuildContext context) async {
|
void setDisplaynameAction(BuildContext context) async {
|
||||||
final input = await showTextInputDialog(
|
final input = await showTextInputDialog(
|
||||||
@ -42,7 +38,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
title: L10n.of(context).changeTheNameOfTheGroup,
|
title: L10n.of(context).changeTheNameOfTheGroup,
|
||||||
textFields: [
|
textFields: [
|
||||||
DialogTextField(
|
DialogTextField(
|
||||||
initialText: widget.room.getLocalizedDisplayname(
|
initialText: room.getLocalizedDisplayname(
|
||||||
MatrixLocals(
|
MatrixLocals(
|
||||||
L10n.of(context),
|
L10n.of(context),
|
||||||
),
|
),
|
||||||
@ -53,7 +49,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
if (input == null) return;
|
if (input == null) return;
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.setName(input.single),
|
future: () => room.setName(input.single),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await FlushbarHelper.createSuccess(
|
await FlushbarHelper.createSuccess(
|
||||||
@ -74,9 +70,9 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
if (input == null) return;
|
if (input == null) return;
|
||||||
final domain = widget.room.client.userID.domain;
|
final domain = room.client.userID.domain;
|
||||||
final canonicalAlias = '%23' + input.single + '%3A' + domain;
|
final canonicalAlias = '%23' + input.single + '%3A' + domain;
|
||||||
final aliasEvent = widget.room.getState('m.room.aliases', domain);
|
final aliasEvent = room.getState('m.room.aliases', domain);
|
||||||
final aliases =
|
final aliases =
|
||||||
aliasEvent != null ? aliasEvent.content['aliases'] ?? [] : [];
|
aliasEvent != null ? aliasEvent.content['aliases'] ?? [] : [];
|
||||||
if (aliases.indexWhere((s) => s == canonicalAlias) == -1) {
|
if (aliases.indexWhere((s) => s == canonicalAlias) == -1) {
|
||||||
@ -84,22 +80,19 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
newAliases.add(canonicalAlias);
|
newAliases.add(canonicalAlias);
|
||||||
final response = await showFutureLoadingDialog(
|
final response = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () =>
|
future: () => room.client.requestRoomAliasInformations(canonicalAlias),
|
||||||
widget.room.client.requestRoomAliasInformations(canonicalAlias),
|
|
||||||
);
|
);
|
||||||
if (response.error != null) {
|
if (response.error != null) {
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.client
|
future: () => room.client.createRoomAlias(canonicalAlias, room.id),
|
||||||
.createRoomAlias(canonicalAlias, widget.room.id),
|
|
||||||
);
|
);
|
||||||
if (success.error != null) return;
|
if (success.error != null) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.client
|
future: () => room.client.sendState(room.id, 'm.room.canonical_alias', {
|
||||||
.sendState(widget.room.id, 'm.room.canonical_alias', {
|
|
||||||
'alias': input.single,
|
'alias': input.single,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -112,7 +105,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
textFields: [
|
textFields: [
|
||||||
DialogTextField(
|
DialogTextField(
|
||||||
hintText: L10n.of(context).setGroupDescription,
|
hintText: L10n.of(context).setGroupDescription,
|
||||||
initialText: widget.room.topic,
|
initialText: room.topic,
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
)
|
)
|
||||||
@ -121,7 +114,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
if (input == null) return;
|
if (input == null) return;
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.setDescription(input.single),
|
future: () => room.setDescription(input.single),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await FlushbarHelper.createSuccess(
|
await FlushbarHelper.createSuccess(
|
||||||
@ -156,7 +149,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
|
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.setAvatar(file),
|
future: () => room.setAvatar(file),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await FlushbarHelper.createSuccess(
|
await FlushbarHelper.createSuccess(
|
||||||
@ -167,7 +160,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
|
|
||||||
void requestMoreMembersAction(BuildContext context) async {
|
void requestMoreMembersAction(BuildContext context) async {
|
||||||
final participants = await showFutureLoadingDialog(
|
final participants = await showFutureLoadingDialog(
|
||||||
context: context, future: () => widget.room.requestParticipants());
|
context: context, future: () => room.requestParticipants());
|
||||||
if (participants.error == null) {
|
if (participants.error == null) {
|
||||||
setState(() => members = participants.result);
|
setState(() => members = participants.result);
|
||||||
}
|
}
|
||||||
@ -175,7 +168,8 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.room == null) {
|
room ??= Matrix.of(context).client.getRoomById(widget.roomId);
|
||||||
|
if (room == null) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(L10n.of(context).oopsSomethingWentWrong),
|
title: Text(L10n.of(context).oopsSomethingWentWrong),
|
||||||
@ -185,381 +179,344 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
members ??= widget.room.getParticipants();
|
members ??= room.getParticipants();
|
||||||
members.removeWhere((u) => u.membership == Membership.leave);
|
members.removeWhere((u) => u.membership == Membership.leave);
|
||||||
final actualMembersCount =
|
final actualMembersCount =
|
||||||
widget.room.mInvitedMemberCount + widget.room.mJoinedMemberCount;
|
room.mInvitedMemberCount + room.mJoinedMemberCount;
|
||||||
final canRequestMoreMembers = members.length < actualMembersCount;
|
final canRequestMoreMembers = members.length < actualMembersCount;
|
||||||
return AdaptivePageLayout(
|
return StreamBuilder(
|
||||||
primaryPage: FocusPage.SECOND,
|
stream: room.onUpdate.stream,
|
||||||
firstScaffold: ChatList(
|
builder: (context, snapshot) {
|
||||||
activeChat: widget.room.id,
|
return Scaffold(
|
||||||
),
|
body: NestedScrollView(
|
||||||
secondScaffold: StreamBuilder(
|
headerSliverBuilder:
|
||||||
stream: widget.room.onUpdate.stream,
|
(BuildContext context, bool innerBoxIsScrolled) => <Widget>[
|
||||||
builder: (context, snapshot) {
|
SliverAppBar(
|
||||||
return Scaffold(
|
expandedHeight: 300.0,
|
||||||
body: NestedScrollView(
|
floating: true,
|
||||||
headerSliverBuilder:
|
pinned: true,
|
||||||
(BuildContext context, bool innerBoxIsScrolled) => <Widget>[
|
actions: <Widget>[
|
||||||
SliverAppBar(
|
if (room.canonicalAlias?.isNotEmpty ?? false)
|
||||||
expandedHeight: 300.0,
|
IconButton(
|
||||||
floating: true,
|
icon: Icon(Icons.share_outlined),
|
||||||
pinned: true,
|
onPressed: () => FluffyShare.share(
|
||||||
actions: <Widget>[
|
AppConfig.inviteLinkPrefix + room.canonicalAlias,
|
||||||
if (widget.room.canonicalAlias?.isNotEmpty ?? false)
|
context),
|
||||||
IconButton(
|
),
|
||||||
icon: Icon(Icons.share_outlined),
|
ChatSettingsPopupMenu(room, false)
|
||||||
onPressed: () => FluffyShare.share(
|
],
|
||||||
AppConfig.inviteLinkPrefix +
|
title: Text(
|
||||||
widget.room.canonicalAlias,
|
room.getLocalizedDisplayname(
|
||||||
context),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
style: TextStyle(
|
||||||
ChatSettingsPopupMenu(widget.room, false)
|
color: Theme.of(context)
|
||||||
],
|
.appBarTheme
|
||||||
title: Text(
|
.textTheme
|
||||||
widget.room.getLocalizedDisplayname(
|
.headline6
|
||||||
MatrixLocals(L10n.of(context))),
|
.color)),
|
||||||
style: TextStyle(
|
backgroundColor: Theme.of(context).appBarTheme.color,
|
||||||
color: Theme.of(context)
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
.appBarTheme
|
background: ContentBanner(room.avatar,
|
||||||
.textTheme
|
onEdit: room.canSendEvent('m.room.avatar')
|
||||||
.headline6
|
? () => setAvatarAction(context)
|
||||||
.color)),
|
: null),
|
||||||
backgroundColor: Theme.of(context).appBarTheme.color,
|
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
|
||||||
background: ContentBanner(widget.room.avatar,
|
|
||||||
onEdit: widget.room.canSendEvent('m.room.avatar')
|
|
||||||
? () => setAvatarAction(context)
|
|
||||||
: null),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
body: ListView.builder(
|
],
|
||||||
itemCount:
|
body: ListView.builder(
|
||||||
members.length + 1 + (canRequestMoreMembers ? 1 : 0),
|
itemCount: members.length + 1 + (canRequestMoreMembers ? 1 : 0),
|
||||||
itemBuilder: (BuildContext context, int i) => i == 0
|
itemBuilder: (BuildContext context, int i) => i == 0
|
||||||
? Column(
|
? Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: widget.room.canSendEvent('m.room.topic')
|
leading: room.canSendEvent('m.room.topic')
|
||||||
? CircleAvatar(
|
? CircleAvatar(
|
||||||
backgroundColor: Theme.of(context)
|
backgroundColor: Theme.of(context)
|
||||||
.scaffoldBackgroundColor,
|
.scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.edit_outlined),
|
child: Icon(Icons.edit_outlined),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
title: Text(
|
title: Text('${L10n.of(context).groupDescription}:',
|
||||||
'${L10n.of(context).groupDescription}:',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
fontWeight: FontWeight.bold)),
|
|
||||||
subtitle: LinkText(
|
|
||||||
text: widget.room.topic?.isEmpty ?? true
|
|
||||||
? L10n.of(context).addGroupDescription
|
|
||||||
: widget.room.topic,
|
|
||||||
linkStyle: TextStyle(color: Colors.blueAccent),
|
|
||||||
textStyle: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyText2
|
|
||||||
.color,
|
|
||||||
),
|
|
||||||
onLinkTap: (url) =>
|
|
||||||
UrlLauncher(context, url).launchUrl(),
|
|
||||||
),
|
|
||||||
onTap: widget.room.canSendEvent('m.room.topic')
|
|
||||||
? () => setTopicAction(context)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
Divider(thickness: 1),
|
|
||||||
ListTile(
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context).settings,
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).primaryColor,
|
color: Theme.of(context).primaryColor,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold)),
|
||||||
),
|
subtitle: LinkText(
|
||||||
|
text: room.topic?.isEmpty ?? true
|
||||||
|
? L10n.of(context).addGroupDescription
|
||||||
|
: room.topic,
|
||||||
|
linkStyle: TextStyle(color: Colors.blueAccent),
|
||||||
|
textStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color:
|
||||||
|
Theme.of(context).textTheme.bodyText2.color,
|
||||||
|
),
|
||||||
|
onLinkTap: (url) =>
|
||||||
|
UrlLauncher(context, url).launchUrl(),
|
||||||
|
),
|
||||||
|
onTap: room.canSendEvent('m.room.topic')
|
||||||
|
? () => setTopicAction(context)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
Divider(thickness: 1),
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).settings,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.room.canSendEvent('m.room.name'))
|
),
|
||||||
ListTile(
|
if (room.canSendEvent('m.room.name'))
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: Colors.grey,
|
|
||||||
child: Icon(Icons.people_outlined),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context).changeTheNameOfTheGroup),
|
|
||||||
subtitle: Text(widget.room
|
|
||||||
.getLocalizedDisplayname(
|
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
onTap: () => setDisplaynameAction(context),
|
|
||||||
),
|
|
||||||
if (widget.room
|
|
||||||
.canSendEvent('m.room.canonical_alias') &&
|
|
||||||
widget.room.joinRules == JoinRules.public)
|
|
||||||
ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: Colors.grey,
|
|
||||||
child: Icon(Icons.link_outlined),
|
|
||||||
),
|
|
||||||
onTap: () => setCanonicalAliasAction(context),
|
|
||||||
title: Text(L10n.of(context).setInvitationLink),
|
|
||||||
subtitle: Text(
|
|
||||||
(widget.room.canonicalAlias?.isNotEmpty ??
|
|
||||||
false)
|
|
||||||
? widget.room.canonicalAlias
|
|
||||||
: L10n.of(context).none),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.insert_emoticon_outlined),
|
child: Icon(Icons.people_outlined),
|
||||||
),
|
),
|
||||||
title: Text(L10n.of(context).emoteSettings),
|
title: Text(
|
||||||
subtitle: Text(L10n.of(context).setCustomEmotes),
|
L10n.of(context).changeTheNameOfTheGroup),
|
||||||
onTap: () async {
|
subtitle: Text(room.getLocalizedDisplayname(
|
||||||
// okay, we need to test if there are any emote state events other than the default one
|
MatrixLocals(L10n.of(context)))),
|
||||||
// if so, we need to be directed to a selection screen for which pack we want to look at
|
onTap: () => setDisplaynameAction(context),
|
||||||
// otherwise, we just open the normal one.
|
|
||||||
if ((widget.room.states
|
|
||||||
.states['im.ponies.room_emotes'] ??
|
|
||||||
<String, Event>{})
|
|
||||||
.keys
|
|
||||||
.any((String s) => s.isNotEmpty)) {
|
|
||||||
await Navigator.of(context).push(
|
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context,
|
|
||||||
MultipleEmotesSettingsView(
|
|
||||||
room: widget.room),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await Navigator.of(context).push(
|
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context,
|
|
||||||
EmotesSettingsView(room: widget.room),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
if (room.canSendEvent('m.room.canonical_alias') &&
|
||||||
|
room.joinRules == JoinRules.public)
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.link_outlined),
|
||||||
|
),
|
||||||
|
onTap: () => setCanonicalAliasAction(context),
|
||||||
|
title: Text(L10n.of(context).setInvitationLink),
|
||||||
|
subtitle: Text(
|
||||||
|
(room.canonicalAlias?.isNotEmpty ?? false)
|
||||||
|
? room.canonicalAlias
|
||||||
|
: L10n.of(context).none),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.insert_emoticon_outlined),
|
||||||
|
),
|
||||||
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
|
subtitle: Text(L10n.of(context).setCustomEmotes),
|
||||||
|
onTap: () async {
|
||||||
|
// okay, we need to test if there are any emote state events other than the default one
|
||||||
|
// if so, we need to be directed to a selection screen for which pack we want to look at
|
||||||
|
// otherwise, we just open the normal one.
|
||||||
|
if ((room.states
|
||||||
|
.states['im.ponies.room_emotes'] ??
|
||||||
|
<String, Event>{})
|
||||||
|
.keys
|
||||||
|
.any((String s) => s.isNotEmpty)) {
|
||||||
|
await AdaptivePageLayout.of(context)
|
||||||
|
.pushNamed('/rooms/${room.id}/emotes');
|
||||||
|
} else {
|
||||||
|
await AdaptivePageLayout.of(context)
|
||||||
|
.pushNamed('/settings/emotes');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
|
child: ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.public_outlined)),
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).whoIsAllowedToJoinThisGroup),
|
||||||
|
subtitle: Text(
|
||||||
|
room.joinRules.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onSelected: (JoinRules joinRule) =>
|
||||||
|
showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => room.setJoinRules(joinRule),
|
||||||
|
),
|
||||||
|
itemBuilder: (BuildContext context) =>
|
||||||
|
<PopupMenuEntry<JoinRules>>[
|
||||||
|
if (room.canChangeJoinRules)
|
||||||
|
PopupMenuItem<JoinRules>(
|
||||||
|
value: JoinRules.public,
|
||||||
|
child: Text(JoinRules.public
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
if (room.canChangeJoinRules)
|
||||||
|
PopupMenuItem<JoinRules>(
|
||||||
|
value: JoinRules.invite,
|
||||||
|
child: Text(JoinRules.invite
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
|
child: ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.visibility_outlined),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).visibilityOfTheChatHistory),
|
||||||
|
subtitle: Text(
|
||||||
|
room.historyVisibility.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onSelected: (HistoryVisibility historyVisibility) =>
|
||||||
|
showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () =>
|
||||||
|
room.setHistoryVisibility(historyVisibility),
|
||||||
|
),
|
||||||
|
itemBuilder: (BuildContext context) =>
|
||||||
|
<PopupMenuEntry<HistoryVisibility>>[
|
||||||
|
if (room.canChangeHistoryVisibility)
|
||||||
|
PopupMenuItem<HistoryVisibility>(
|
||||||
|
value: HistoryVisibility.invited,
|
||||||
|
child: Text(HistoryVisibility.invited
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
if (room.canChangeHistoryVisibility)
|
||||||
|
PopupMenuItem<HistoryVisibility>(
|
||||||
|
value: HistoryVisibility.joined,
|
||||||
|
child: Text(HistoryVisibility.joined
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
if (room.canChangeHistoryVisibility)
|
||||||
|
PopupMenuItem<HistoryVisibility>(
|
||||||
|
value: HistoryVisibility.shared,
|
||||||
|
child: Text(HistoryVisibility.shared
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
if (room.canChangeHistoryVisibility)
|
||||||
|
PopupMenuItem<HistoryVisibility>(
|
||||||
|
value: HistoryVisibility.world_readable,
|
||||||
|
child: Text(HistoryVisibility.world_readable
|
||||||
|
.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context)))),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (room.joinRules == JoinRules.public)
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor: Theme.of(context)
|
backgroundColor:
|
||||||
.scaffoldBackgroundColor,
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.public_outlined)),
|
child: Icon(Icons.info_outline),
|
||||||
title: Text(L10n.of(context)
|
),
|
||||||
.whoIsAllowedToJoinThisGroup),
|
title: Text(
|
||||||
|
L10n.of(context).areGuestsAllowedToJoin),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
widget.room.joinRules.getLocalizedString(
|
room.guestAccess.getLocalizedString(
|
||||||
MatrixLocals(L10n.of(context))),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onSelected: (JoinRules joinRule) =>
|
onSelected: (GuestAccess guestAccess) =>
|
||||||
showFutureLoadingDialog(
|
showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () =>
|
future: () => room.setGuestAccess(guestAccess),
|
||||||
widget.room.setJoinRules(joinRule),
|
|
||||||
),
|
),
|
||||||
itemBuilder: (BuildContext context) =>
|
itemBuilder: (BuildContext context) =>
|
||||||
<PopupMenuEntry<JoinRules>>[
|
<PopupMenuEntry<GuestAccess>>[
|
||||||
if (widget.room.canChangeJoinRules)
|
if (room.canChangeGuestAccess)
|
||||||
PopupMenuItem<JoinRules>(
|
PopupMenuItem<GuestAccess>(
|
||||||
value: JoinRules.public,
|
value: GuestAccess.can_join,
|
||||||
child: Text(JoinRules.public
|
child: Text(
|
||||||
.getLocalizedString(
|
GuestAccess.can_join.getLocalizedString(
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
),
|
|
||||||
if (widget.room.canChangeJoinRules)
|
|
||||||
PopupMenuItem<JoinRules>(
|
|
||||||
value: JoinRules.invite,
|
|
||||||
child: Text(JoinRules.invite
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
PopupMenuButton(
|
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: Colors.grey,
|
|
||||||
child: Icon(Icons.visibility_outlined),
|
|
||||||
),
|
|
||||||
title: Text(L10n.of(context)
|
|
||||||
.visibilityOfTheChatHistory),
|
|
||||||
subtitle: Text(
|
|
||||||
widget.room.historyVisibility
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context))),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
onSelected:
|
|
||||||
(HistoryVisibility historyVisibility) =>
|
|
||||||
showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => widget.room
|
|
||||||
.setHistoryVisibility(historyVisibility),
|
|
||||||
),
|
|
||||||
itemBuilder: (BuildContext context) =>
|
|
||||||
<PopupMenuEntry<HistoryVisibility>>[
|
|
||||||
if (widget.room.canChangeHistoryVisibility)
|
|
||||||
PopupMenuItem<HistoryVisibility>(
|
|
||||||
value: HistoryVisibility.invited,
|
|
||||||
child: Text(HistoryVisibility.invited
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
),
|
),
|
||||||
if (widget.room.canChangeHistoryVisibility)
|
if (room.canChangeGuestAccess)
|
||||||
PopupMenuItem<HistoryVisibility>(
|
PopupMenuItem<GuestAccess>(
|
||||||
value: HistoryVisibility.joined,
|
value: GuestAccess.forbidden,
|
||||||
child: Text(HistoryVisibility.joined
|
child: Text(
|
||||||
.getLocalizedString(
|
GuestAccess.forbidden.getLocalizedString(
|
||||||
MatrixLocals(L10n.of(context)))),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
),
|
||||||
if (widget.room.canChangeHistoryVisibility)
|
|
||||||
PopupMenuItem<HistoryVisibility>(
|
|
||||||
value: HistoryVisibility.shared,
|
|
||||||
child: Text(HistoryVisibility.shared
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
),
|
|
||||||
if (widget.room.canChangeHistoryVisibility)
|
|
||||||
PopupMenuItem<HistoryVisibility>(
|
|
||||||
value: HistoryVisibility.world_readable,
|
|
||||||
child: Text(HistoryVisibility.world_readable
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)))),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (widget.room.joinRules == JoinRules.public)
|
ListTile(
|
||||||
PopupMenuButton(
|
title: Text(L10n.of(context).editChatPermissions),
|
||||||
child: ListTile(
|
subtitle:
|
||||||
|
Text(L10n.of(context).whoCanPerformWhichAction),
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.edit_attributes_outlined),
|
||||||
|
),
|
||||||
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
|
.pushNamed('/rooms/${room.id}/permissions'),
|
||||||
|
),
|
||||||
|
Divider(thickness: 1),
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
actualMembersCount > 1
|
||||||
|
? L10n.of(context).countParticipants(
|
||||||
|
actualMembersCount.toString())
|
||||||
|
: L10n.of(context).emptyChat,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
room.canInvite
|
||||||
|
? ListTile(
|
||||||
|
title: Text(L10n.of(context).inviteContact),
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor: Theme.of(context)
|
child: Icon(Icons.add_outlined),
|
||||||
.scaffoldBackgroundColor,
|
backgroundColor:
|
||||||
foregroundColor: Colors.grey,
|
Theme.of(context).primaryColor,
|
||||||
child: Icon(Icons.info_outline),
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
title: Text(
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
L10n.of(context).areGuestsAllowedToJoin),
|
.pushNamed('/rooms/${room.id}/invite'),
|
||||||
subtitle: Text(
|
)
|
||||||
widget.room.guestAccess.getLocalizedString(
|
: Container(),
|
||||||
MatrixLocals(L10n.of(context))),
|
],
|
||||||
),
|
)
|
||||||
),
|
: i < members.length + 1
|
||||||
onSelected: (GuestAccess guestAccess) =>
|
? ParticipantListItem(members[i - 1])
|
||||||
showFutureLoadingDialog(
|
: ListTile(
|
||||||
context: context,
|
title: Text(L10n.of(context)
|
||||||
future: () =>
|
.loadCountMoreParticipants(
|
||||||
widget.room.setGuestAccess(guestAccess),
|
(actualMembersCount - members.length)
|
||||||
),
|
.toString())),
|
||||||
itemBuilder: (BuildContext context) =>
|
leading: CircleAvatar(
|
||||||
<PopupMenuEntry<GuestAccess>>[
|
backgroundColor:
|
||||||
if (widget.room.canChangeGuestAccess)
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
PopupMenuItem<GuestAccess>(
|
child: Icon(
|
||||||
value: GuestAccess.can_join,
|
Icons.refresh,
|
||||||
child: Text(
|
color: Colors.grey,
|
||||||
GuestAccess.can_join.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (widget.room.canChangeGuestAccess)
|
|
||||||
PopupMenuItem<GuestAccess>(
|
|
||||||
value: GuestAccess.forbidden,
|
|
||||||
child: Text(
|
|
||||||
GuestAccess.forbidden
|
|
||||||
.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
title: Text(L10n.of(context).editChatPermissions),
|
|
||||||
subtitle: Text(
|
|
||||||
L10n.of(context).whoCanPerformWhichAction),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: Colors.grey,
|
|
||||||
child: Icon(Icons.edit_attributes_outlined),
|
|
||||||
),
|
|
||||||
onTap: () => Navigator.of(context).push(
|
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context,
|
|
||||||
ChatPermissionsSettingsView(
|
|
||||||
roomId: widget.room.id),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(thickness: 1),
|
onTap: () => requestMoreMembersAction(context),
|
||||||
ListTile(
|
),
|
||||||
title: Text(
|
|
||||||
actualMembersCount > 1
|
|
||||||
? L10n.of(context).countParticipants(
|
|
||||||
actualMembersCount.toString())
|
|
||||||
: L10n.of(context).emptyChat,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
widget.room.canInvite
|
|
||||||
? ListTile(
|
|
||||||
title: Text(L10n.of(context).inviteContact),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
child: Icon(Icons.add_outlined),
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).primaryColor,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
onTap: () => Navigator.of(context).push(
|
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context,
|
|
||||||
InvitationSelection(widget.room),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: i < members.length + 1
|
|
||||||
? ParticipantListItem(members[i - 1])
|
|
||||||
: ListTile(
|
|
||||||
title: Text(L10n.of(context)
|
|
||||||
.loadCountMoreParticipants(
|
|
||||||
(actualMembersCount - members.length)
|
|
||||||
.toString())),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
child: Icon(
|
|
||||||
Icons.refresh,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () => requestMoreMembersAction(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}),
|
);
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,14 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:famedlysdk/encryption.dart';
|
import 'package:famedlysdk/encryption.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/beautify_string_extension.dart';
|
import 'package:fluffychat/utils/beautify_string_extension.dart';
|
||||||
import 'package:fluffychat/views/chat_list.dart';
|
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.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 '../components/dialogs/key_verification_dialog.dart';
|
import '../components/dialogs/key_verification_dialog.dart';
|
||||||
|
|
||||||
class ChatEncryptionSettingsView extends StatelessWidget {
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
const ChatEncryptionSettingsView(this.id, {Key key}) : super(key: key);
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
firstScaffold: ChatList(
|
|
||||||
activeChat: id,
|
|
||||||
),
|
|
||||||
secondScaffold: ChatEncryptionSettings(id),
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChatEncryptionSettings extends StatefulWidget {
|
class ChatEncryptionSettings extends StatefulWidget {
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/connection_status_header.dart';
|
import 'package:fluffychat/components/connection_status_header.dart';
|
||||||
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
||||||
@ -14,29 +15,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
|
||||||
|
|
||||||
import '../components/adaptive_page_layout.dart';
|
|
||||||
import '../components/list_items/chat_list_item.dart';
|
import '../components/list_items/chat_list_item.dart';
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import '../utils/app_route.dart';
|
|
||||||
import '../utils/matrix_file_extension.dart';
|
import '../utils/matrix_file_extension.dart';
|
||||||
import '../utils/url_launcher.dart';
|
import '../utils/url_launcher.dart';
|
||||||
import 'empty_page.dart';
|
|
||||||
import 'homeserver_picker.dart';
|
|
||||||
import 'new_private_chat.dart';
|
|
||||||
|
|
||||||
enum SelectMode { normal, share, select }
|
enum SelectMode { normal, share, select }
|
||||||
|
|
||||||
class ChatListView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.FIRST,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: EmptyPage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChatList extends StatefulWidget {
|
class ChatList extends StatefulWidget {
|
||||||
final String activeChat;
|
final String activeChat;
|
||||||
|
|
||||||
@ -86,9 +71,7 @@ class _ChatListState extends State<ChatList> {
|
|||||||
|
|
||||||
void _processIncomingSharedFiles(List<SharedMediaFile> files) {
|
void _processIncomingSharedFiles(List<SharedMediaFile> files) {
|
||||||
if (files?.isEmpty ?? true) return;
|
if (files?.isEmpty ?? true) return;
|
||||||
if (Navigator.of(context).canPop()) {
|
AdaptivePageLayout.of(context).popUntilIsFirst();
|
||||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
|
||||||
}
|
|
||||||
final file = File(files.first.path);
|
final file = File(files.first.path);
|
||||||
|
|
||||||
Matrix.of(context).shareContent = {
|
Matrix.of(context).shareContent = {
|
||||||
@ -102,9 +85,7 @@ class _ChatListState extends State<ChatList> {
|
|||||||
|
|
||||||
void _processIncomingSharedText(String text) {
|
void _processIncomingSharedText(String text) {
|
||||||
if (text == null) return;
|
if (text == null) return;
|
||||||
if (Navigator.of(context).canPop()) {
|
AdaptivePageLayout.of(context).popUntilIsFirst();
|
||||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
|
||||||
}
|
|
||||||
if (text.toLowerCase().startsWith(AppConfig.inviteLinkPrefix) ||
|
if (text.toLowerCase().startsWith(AppConfig.inviteLinkPrefix) ||
|
||||||
(text.toLowerCase().startsWith(AppConfig.schemePrefix) &&
|
(text.toLowerCase().startsWith(AppConfig.schemePrefix) &&
|
||||||
!RegExp(r'\s').hasMatch(text))) {
|
!RegExp(r'\s').hasMatch(text))) {
|
||||||
@ -194,205 +175,178 @@ class _ChatListState extends State<ChatList> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<LoginState>(
|
return StreamBuilder(
|
||||||
stream: Matrix.of(context).client.onLoginStateChanged.stream,
|
stream: Matrix.of(context).onShareContentChanged.stream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.data == LoginState.loggedOut) {
|
final selectMode = Matrix.of(context).shareContent == null
|
||||||
Timer(Duration(seconds: 1), () {
|
? _selectedRoomIds.isEmpty
|
||||||
Matrix.of(context).clean();
|
? SelectMode.normal
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
: SelectMode.select
|
||||||
AppRoute.defaultRoute(context, HomeserverPicker()),
|
: SelectMode.share;
|
||||||
(r) => false);
|
if (selectMode == SelectMode.share) {
|
||||||
});
|
_selectedRoomIds.clear();
|
||||||
}
|
}
|
||||||
return StreamBuilder(
|
Room selectedRoom;
|
||||||
stream: Matrix.of(context).onShareContentChanged.stream,
|
if (_selectedRoomIds.length == 1) {
|
||||||
builder: (context, snapshot) {
|
selectedRoom =
|
||||||
final selectMode = Matrix.of(context).shareContent == null
|
Matrix.of(context).client.getRoomById(_selectedRoomIds.single);
|
||||||
? _selectedRoomIds.isEmpty
|
}
|
||||||
? SelectMode.normal
|
return Scaffold(
|
||||||
: SelectMode.select
|
drawer: selectMode != SelectMode.normal ? null : DefaultDrawer(),
|
||||||
: SelectMode.share;
|
appBar: AppBar(
|
||||||
if (selectMode == SelectMode.share) {
|
centerTitle: false,
|
||||||
_selectedRoomIds.clear();
|
elevation: _scrolledToTop ? 0 : null,
|
||||||
}
|
leading: selectMode == SelectMode.share
|
||||||
Room selectedRoom;
|
? IconButton(
|
||||||
if (_selectedRoomIds.length == 1) {
|
icon: Icon(Icons.close),
|
||||||
selectedRoom = Matrix.of(context)
|
onPressed: () => Matrix.of(context).shareContent = null,
|
||||||
.client
|
)
|
||||||
.getRoomById(_selectedRoomIds.single);
|
: selectMode == SelectMode.select
|
||||||
}
|
? IconButton(
|
||||||
return Scaffold(
|
icon: Icon(Icons.close),
|
||||||
drawer:
|
onPressed: () => setState(_selectedRoomIds.clear),
|
||||||
selectMode != SelectMode.normal ? null : DefaultDrawer(),
|
)
|
||||||
appBar: AppBar(
|
: null,
|
||||||
centerTitle: false,
|
titleSpacing: 0,
|
||||||
elevation: _scrolledToTop ? 0 : null,
|
actions: selectMode != SelectMode.select
|
||||||
leading: selectMode == SelectMode.share
|
? null
|
||||||
? IconButton(
|
: [
|
||||||
icon: Icon(Icons.close),
|
if (_selectedRoomIds.length == 1)
|
||||||
onPressed: () =>
|
IconButton(
|
||||||
Matrix.of(context).shareContent = null,
|
tooltip: L10n.of(context).toggleUnread,
|
||||||
)
|
icon: Icon(selectedRoom.isUnread
|
||||||
: selectMode == SelectMode.select
|
? Icons.mark_chat_read_outlined
|
||||||
? IconButton(
|
: Icons.mark_chat_unread_outlined),
|
||||||
icon: Icon(Icons.close),
|
onPressed: () => _toggleUnread(context),
|
||||||
onPressed: () =>
|
|
||||||
setState(_selectedRoomIds.clear),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
titleSpacing: 0,
|
|
||||||
actions: selectMode != SelectMode.select
|
|
||||||
? null
|
|
||||||
: [
|
|
||||||
if (_selectedRoomIds.length == 1)
|
|
||||||
IconButton(
|
|
||||||
tooltip: L10n.of(context).toggleUnread,
|
|
||||||
icon: Icon(selectedRoom.isUnread
|
|
||||||
? Icons.mark_chat_read_outlined
|
|
||||||
: Icons.mark_chat_unread_outlined),
|
|
||||||
onPressed: () => _toggleUnread(context),
|
|
||||||
),
|
|
||||||
if (_selectedRoomIds.length == 1)
|
|
||||||
IconButton(
|
|
||||||
tooltip: L10n.of(context).toggleFavorite,
|
|
||||||
icon: Icon(Icons.push_pin_outlined),
|
|
||||||
onPressed: () => _toggleFavouriteRoom(context),
|
|
||||||
),
|
|
||||||
if (_selectedRoomIds.length == 1)
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(selectedRoom.pushRuleState ==
|
|
||||||
PushRuleState.notify
|
|
||||||
? Icons.notifications_off_outlined
|
|
||||||
: Icons.notifications_outlined),
|
|
||||||
tooltip: L10n.of(context).toggleMuted,
|
|
||||||
onPressed: () => _toggleMuted(context),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.archive_outlined),
|
|
||||||
tooltip: L10n.of(context).archive,
|
|
||||||
onPressed: () => _archiveAction(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
title: selectMode == SelectMode.share
|
|
||||||
? Text(L10n.of(context).share)
|
|
||||||
: selectMode == SelectMode.select
|
|
||||||
? Text(_selectedRoomIds.length.toString())
|
|
||||||
: DefaultAppBarSearchField(
|
|
||||||
searchController: searchController,
|
|
||||||
hintText: L10n.of(context).searchForAChat,
|
|
||||||
onChanged: (_) => setState(() => null),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: AdaptivePageLayout.columnMode(context)
|
|
||||||
? null
|
|
||||||
: FloatingActionButton(
|
|
||||||
child: Icon(Icons.add_outlined),
|
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
|
||||||
onPressed: () => Navigator.of(context)
|
|
||||||
.pushAndRemoveUntil(
|
|
||||||
AppRoute.defaultRoute(
|
|
||||||
context, NewPrivateChatView()),
|
|
||||||
(r) => r.isFirst),
|
|
||||||
),
|
),
|
||||||
body: Column(
|
if (_selectedRoomIds.length == 1)
|
||||||
children: [
|
IconButton(
|
||||||
ConnectionStatusHeader(),
|
tooltip: L10n.of(context).toggleFavorite,
|
||||||
Expanded(
|
icon: Icon(Icons.push_pin_outlined),
|
||||||
child: StreamBuilder(
|
onPressed: () => _toggleFavouriteRoom(context),
|
||||||
stream: Matrix.of(context)
|
),
|
||||||
.client
|
if (_selectedRoomIds.length == 1)
|
||||||
.onSync
|
IconButton(
|
||||||
.stream
|
icon: Icon(
|
||||||
.where((s) => s.hasRoomUpdate),
|
selectedRoom.pushRuleState == PushRuleState.notify
|
||||||
builder: (context, snapshot) {
|
? Icons.notifications_off_outlined
|
||||||
return FutureBuilder<void>(
|
: Icons.notifications_outlined),
|
||||||
future: waitForFirstSync(context),
|
tooltip: L10n.of(context).toggleMuted,
|
||||||
builder: (BuildContext context, snapshot) {
|
onPressed: () => _toggleMuted(context),
|
||||||
if (snapshot.hasData) {
|
),
|
||||||
var rooms = List<Room>.from(
|
IconButton(
|
||||||
Matrix.of(context).client.rooms);
|
icon: Icon(Icons.archive_outlined),
|
||||||
rooms.removeWhere((Room room) =>
|
tooltip: L10n.of(context).archive,
|
||||||
room.lastEvent == null ||
|
onPressed: () => _archiveAction(context),
|
||||||
(searchMode &&
|
|
||||||
!room.displayname
|
|
||||||
.toLowerCase()
|
|
||||||
.contains(searchController.text
|
|
||||||
.toLowerCase() ??
|
|
||||||
'')));
|
|
||||||
if (rooms.isEmpty && (!searchMode)) {
|
|
||||||
return Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(
|
|
||||||
searchMode
|
|
||||||
? Icons.search_outlined
|
|
||||||
: Icons.chat_bubble_outline,
|
|
||||||
size: 80,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
Text(searchMode
|
|
||||||
? L10n.of(context).noRoomsFound
|
|
||||||
: L10n.of(context)
|
|
||||||
.startYourFirstChat),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final totalCount = rooms.length;
|
|
||||||
return ListView.separated(
|
|
||||||
controller: _scrollController,
|
|
||||||
separatorBuilder: (BuildContext context,
|
|
||||||
int i) =>
|
|
||||||
i == totalCount
|
|
||||||
? ListTile(
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context)
|
|
||||||
.publicRooms +
|
|
||||||
':',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.bold,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Container(),
|
|
||||||
itemCount: totalCount,
|
|
||||||
itemBuilder:
|
|
||||||
(BuildContext context, int i) =>
|
|
||||||
ChatListItem(
|
|
||||||
rooms[i],
|
|
||||||
selected: _selectedRoomIds
|
|
||||||
.contains(rooms[i].id),
|
|
||||||
onTap: selectMode == SelectMode.select
|
|
||||||
? () =>
|
|
||||||
_toggleSelection(rooms[i].id)
|
|
||||||
: null,
|
|
||||||
onLongPress: selectMode !=
|
|
||||||
SelectMode.share
|
|
||||||
? () =>
|
|
||||||
_toggleSelection(rooms[i].id)
|
|
||||||
: null,
|
|
||||||
activeChat:
|
|
||||||
widget.activeChat == rooms[i].id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
title: selectMode == SelectMode.share
|
||||||
);
|
? Text(L10n.of(context).share)
|
||||||
});
|
: selectMode == SelectMode.select
|
||||||
|
? Text(_selectedRoomIds.length.toString())
|
||||||
|
: DefaultAppBarSearchField(
|
||||||
|
searchController: searchController,
|
||||||
|
hintText: L10n.of(context).searchForAChat,
|
||||||
|
onChanged: (_) => setState(() => null),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton:
|
||||||
|
AdaptivePageLayout.of(context).columnMode(context)
|
||||||
|
? null
|
||||||
|
: FloatingActionButton(
|
||||||
|
child: Icon(Icons.add_outlined),
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
onPressed: () => AdaptivePageLayout.of(context)
|
||||||
|
.pushNamedAndRemoveUntilIsFirst('/newprivatechat'),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
ConnectionStatusHeader(),
|
||||||
|
Expanded(
|
||||||
|
child: StreamBuilder(
|
||||||
|
stream: Matrix.of(context)
|
||||||
|
.client
|
||||||
|
.onSync
|
||||||
|
.stream
|
||||||
|
.where((s) => s.hasRoomUpdate),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return FutureBuilder<void>(
|
||||||
|
future: waitForFirstSync(context),
|
||||||
|
builder: (BuildContext context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
var rooms = List<Room>.from(
|
||||||
|
Matrix.of(context).client.rooms);
|
||||||
|
rooms.removeWhere((Room room) =>
|
||||||
|
room.lastEvent == null ||
|
||||||
|
(searchMode &&
|
||||||
|
!room.displayname.toLowerCase().contains(
|
||||||
|
searchController.text.toLowerCase() ??
|
||||||
|
'')));
|
||||||
|
if (rooms.isEmpty && (!searchMode)) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(
|
||||||
|
searchMode
|
||||||
|
? Icons.search_outlined
|
||||||
|
: Icons.chat_bubble_outline,
|
||||||
|
size: 80,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
Text(searchMode
|
||||||
|
? L10n.of(context).noRoomsFound
|
||||||
|
: L10n.of(context)
|
||||||
|
.startYourFirstChat),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final totalCount = rooms.length;
|
||||||
|
return ListView.separated(
|
||||||
|
controller: _scrollController,
|
||||||
|
separatorBuilder:
|
||||||
|
(BuildContext context, int i) =>
|
||||||
|
i == totalCount
|
||||||
|
? ListTile(
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).publicRooms +
|
||||||
|
':',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
itemCount: totalCount,
|
||||||
|
itemBuilder: (BuildContext context, int i) =>
|
||||||
|
ChatListItem(
|
||||||
|
rooms[i],
|
||||||
|
selected:
|
||||||
|
_selectedRoomIds.contains(rooms[i].id),
|
||||||
|
onTap: selectMode == SelectMode.select
|
||||||
|
? () => _toggleSelection(rooms[i].id)
|
||||||
|
: null,
|
||||||
|
onLongPress: selectMode != SelectMode.share
|
||||||
|
? () => _toggleSelection(rooms[i].id)
|
||||||
|
: null,
|
||||||
|
activeChat: widget.activeChat == rooms[i].id,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
|
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
@ -9,29 +8,10 @@ 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 'chat_list.dart';
|
|
||||||
|
|
||||||
class ChatPermissionsSettingsView extends StatelessWidget {
|
|
||||||
final String roomId;
|
|
||||||
|
|
||||||
const ChatPermissionsSettingsView({Key key, this.roomId}) : super(key: key);
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
firstScaffold: ChatList(
|
|
||||||
activeChat: roomId,
|
|
||||||
),
|
|
||||||
secondScaffold: ChatPermissionsSettings(roomId: roomId),
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChatPermissionsSettings extends StatelessWidget {
|
class ChatPermissionsSettings extends StatelessWidget {
|
||||||
final String roomId;
|
final String roomId;
|
||||||
|
|
||||||
const ChatPermissionsSettings({Key key, @required this.roomId})
|
const ChatPermissionsSettings(this.roomId, {Key key}) : super(key: key);
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
void _editPowerLevel(BuildContext context, String key, int currentLevel,
|
void _editPowerLevel(BuildContext context, String key, int currentLevel,
|
||||||
{String category}) async {
|
{String category}) async {
|
||||||
|
@ -1,32 +1,15 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/chat.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 'empty_page.dart';
|
|
||||||
|
|
||||||
class DiscoverView extends StatelessWidget {
|
|
||||||
final String alias;
|
|
||||||
|
|
||||||
const DiscoverView({Key key, this.alias}) : super(key: key);
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
firstScaffold: DiscoverPage(alias: alias),
|
|
||||||
secondScaffold: EmptyPage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DiscoverPage extends StatefulWidget {
|
class DiscoverPage extends StatefulWidget {
|
||||||
final String alias;
|
final String alias;
|
||||||
|
|
||||||
@ -110,12 +93,8 @@ class _DiscoverPageState extends State<DiscoverPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamedAndRemoveUntilIsFirst('/rooms/${success.result}');
|
||||||
context,
|
|
||||||
ChatView(success.result),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/app_config.dart';
|
import 'package:fluffychat/app_config.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/sentry_controller.dart';
|
import 'package:fluffychat/utils/sentry_controller.dart';
|
||||||
import 'package:fluffychat/views/sign_up.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import 'login.dart';
|
|
||||||
|
|
||||||
class HomeserverPicker extends StatelessWidget {
|
class HomeserverPicker extends StatelessWidget {
|
||||||
Future<void> _setHomeserverAction(BuildContext context) async {
|
Future<void> _setHomeserverAction(BuildContext context) async {
|
||||||
const prefix = 'https://';
|
const prefix = 'https://';
|
||||||
@ -45,8 +42,8 @@ class HomeserverPicker extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
future: () => checkHomeserver(homeserver, Matrix.of(context).client));
|
future: () => checkHomeserver(homeserver, Matrix.of(context).client));
|
||||||
if (success.result == true) {
|
if (success.result == true) {
|
||||||
await Navigator.of(context)
|
await AdaptivePageLayout.of(context)
|
||||||
.push(AppRoute(AppConfig.enableRegistration ? SignUp() : Login()));
|
.pushNamed(AppConfig.enableRegistration ? '/signup' : '/login');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/image_bubble.dart';
|
import 'package:fluffychat/components/image_bubble.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
@ -13,7 +14,7 @@ class ImageView extends StatelessWidget {
|
|||||||
|
|
||||||
void _forwardAction(BuildContext context) async {
|
void _forwardAction(BuildContext context) async {
|
||||||
Matrix.of(context).shareContent = event.content;
|
Matrix.of(context).shareContent = event.content;
|
||||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
AdaptivePageLayout.of(context).popUntilIsFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -3,7 +3,6 @@ import 'dart:async';
|
|||||||
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
import 'package:fluffychat/components/default_app_bar_search_field.dart';
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
@ -11,11 +10,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
import '../utils/localized_exception_extension.dart';
|
import '../utils/localized_exception_extension.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class InvitationSelection extends StatefulWidget {
|
class InvitationSelection extends StatefulWidget {
|
||||||
final Room room;
|
final String roomId;
|
||||||
const InvitationSelection(this.room, {Key key}) : super(key: key);
|
const InvitationSelection(this.roomId, {Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_InvitationSelectionState createState() => _InvitationSelectionState();
|
_InvitationSelectionState createState() => _InvitationSelectionState();
|
||||||
@ -27,11 +25,12 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||||||
bool loading = false;
|
bool loading = false;
|
||||||
List<Profile> foundProfiles = [];
|
List<Profile> foundProfiles = [];
|
||||||
Timer coolDown;
|
Timer coolDown;
|
||||||
|
Room room;
|
||||||
|
|
||||||
Future<List<User>> getContacts(BuildContext context) async {
|
Future<List<User>> getContacts(BuildContext context) async {
|
||||||
var client2 = Matrix.of(context).client;
|
var client2 = Matrix.of(context).client;
|
||||||
final client = client2;
|
final client = client2;
|
||||||
var participants = await widget.room.requestParticipants();
|
var participants = await room.requestParticipants();
|
||||||
participants.removeWhere(
|
participants.removeWhere(
|
||||||
(u) => ![Membership.join, Membership.invite].contains(u.membership),
|
(u) => ![Membership.join, Membership.invite].contains(u.membership),
|
||||||
);
|
);
|
||||||
@ -59,7 +58,7 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||||||
void inviteAction(BuildContext context, String id) async {
|
void inviteAction(BuildContext context, String id) async {
|
||||||
final success = await showFutureLoadingDialog(
|
final success = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.room.invite(id),
|
future: () => room.invite(id),
|
||||||
);
|
);
|
||||||
if (success.error == null) {
|
if (success.error == null) {
|
||||||
await FlushbarHelper.createSuccess(
|
await FlushbarHelper.createSuccess(
|
||||||
@ -107,7 +106,7 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||||||
Profile.fromJson({'user_id': '@$text'}),
|
Profile.fromJson({'user_id': '@$text'}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
final participants = widget.room
|
final participants = room
|
||||||
.getParticipants()
|
.getParticipants()
|
||||||
.where((user) =>
|
.where((user) =>
|
||||||
[Membership.join, Membership.invite].contains(user.membership))
|
[Membership.join, Membership.invite].contains(user.membership))
|
||||||
@ -119,60 +118,57 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final groupName = widget.room.name?.isEmpty ?? false
|
room ??= Matrix.of(context).client.getRoomById(widget.roomId);
|
||||||
? L10n.of(context).group
|
final groupName =
|
||||||
: widget.room.name;
|
room.name?.isEmpty ?? false ? L10n.of(context).group : room.name;
|
||||||
return AdaptivePageLayout(
|
return Scaffold(
|
||||||
primaryPage: FocusPage.SECOND,
|
appBar: AppBar(
|
||||||
firstScaffold: ChatList(activeChat: widget.room.id),
|
titleSpacing: 0,
|
||||||
secondScaffold: Scaffold(
|
title: DefaultAppBarSearchField(
|
||||||
appBar: AppBar(
|
autofocus: true,
|
||||||
titleSpacing: 0,
|
hintText: L10n.of(context).inviteContactToGroup(groupName),
|
||||||
title: DefaultAppBarSearchField(
|
onChanged: (String text) => searchUserWithCoolDown(context, text),
|
||||||
autofocus: true,
|
),
|
||||||
hintText: L10n.of(context).inviteContactToGroup(groupName),
|
),
|
||||||
onChanged: (String text) => searchUserWithCoolDown(context, text),
|
body: foundProfiles.isNotEmpty
|
||||||
),
|
? ListView.builder(
|
||||||
),
|
itemCount: foundProfiles.length,
|
||||||
body: foundProfiles.isNotEmpty
|
itemBuilder: (BuildContext context, int i) => ListTile(
|
||||||
? ListView.builder(
|
leading: Avatar(
|
||||||
itemCount: foundProfiles.length,
|
foundProfiles[i].avatarUrl,
|
||||||
|
foundProfiles[i].displayname ?? foundProfiles[i].userId,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
foundProfiles[i].displayname ??
|
||||||
|
foundProfiles[i].userId.localpart,
|
||||||
|
),
|
||||||
|
subtitle: Text(foundProfiles[i].userId),
|
||||||
|
onTap: () => inviteAction(context, foundProfiles[i].userId),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: FutureBuilder<List<User>>(
|
||||||
|
future: getContacts(context),
|
||||||
|
builder: (BuildContext context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var contacts = snapshot.data;
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: contacts.length,
|
||||||
itemBuilder: (BuildContext context, int i) => ListTile(
|
itemBuilder: (BuildContext context, int i) => ListTile(
|
||||||
leading: Avatar(
|
leading: Avatar(
|
||||||
foundProfiles[i].avatarUrl,
|
contacts[i].avatarUrl,
|
||||||
foundProfiles[i].displayname ?? foundProfiles[i].userId,
|
contacts[i].calcDisplayname(),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(contacts[i].calcDisplayname()),
|
||||||
foundProfiles[i].displayname ??
|
subtitle: Text(contacts[i].id),
|
||||||
foundProfiles[i].userId.localpart,
|
onTap: () => inviteAction(context, contacts[i].id),
|
||||||
),
|
|
||||||
subtitle: Text(foundProfiles[i].userId),
|
|
||||||
onTap: () => inviteAction(context, foundProfiles[i].userId),
|
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
: FutureBuilder<List<User>>(
|
},
|
||||||
future: getContacts(context),
|
),
|
||||||
builder: (BuildContext context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
var contacts = snapshot.data;
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: contacts.length,
|
|
||||||
itemBuilder: (BuildContext context, int i) => ListTile(
|
|
||||||
leading: Avatar(
|
|
||||||
contacts[i].avatarUrl,
|
|
||||||
contacts[i].calcDisplayname(),
|
|
||||||
),
|
|
||||||
title: Text(contacts[i].calcDisplayname()),
|
|
||||||
subtitle: Text(contacts[i].id),
|
|
||||||
onTap: () => inviteAction(context, contacts[i].id),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
lib/views/loading_view.dart
Normal file
38
lib/views/loading_view.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
|
import 'chat_list.dart';
|
||||||
|
import 'homeserver_picker.dart';
|
||||||
|
|
||||||
|
class LoadingView extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<LoginState>(
|
||||||
|
future: Matrix.of(context).client.onLoginStateChanged.stream.first,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasError) {
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => FlushbarHelper.createError(
|
||||||
|
title: L10n.of(context).oopsSomethingWentWrong,
|
||||||
|
message: snapshot.error.toString(),
|
||||||
|
).show(context));
|
||||||
|
return HomeserverPicker();
|
||||||
|
}
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (Matrix.of(context).client.isLogged()) {
|
||||||
|
return ChatList();
|
||||||
|
}
|
||||||
|
return HomeserverPicker();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -5,15 +5,10 @@ import 'package:adaptive_dialog/adaptive_dialog.dart';
|
|||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/firebase_controller.dart';
|
|
||||||
import 'package:fluffychat/utils/sentry_controller.dart';
|
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.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 'chat_list.dart';
|
|
||||||
|
|
||||||
class Login extends StatefulWidget {
|
class Login extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_LoginState createState() => _LoginState();
|
_LoginState createState() => _LoginState();
|
||||||
@ -57,14 +52,8 @@ class _LoginState extends State<Login> {
|
|||||||
setState(() => passwordError = exception.toString());
|
setState(() => passwordError = exception.toString());
|
||||||
return setState(() => loading = false);
|
return setState(() => loading = false);
|
||||||
}
|
}
|
||||||
await FirebaseController.setupFirebase(
|
|
||||||
matrix,
|
|
||||||
matrix.clientName,
|
|
||||||
).catchError(SentryController.captureException);
|
|
||||||
|
|
||||||
setState(() => loading = false);
|
if (mounted) setState(() => loading = false);
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
|
||||||
AppRoute.defaultRoute(context, ChatListView()), (r) => false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer _coolDown;
|
Timer _coolDown;
|
||||||
|
@ -1,33 +1,16 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart' as sdk;
|
import 'package:famedlysdk/famedlysdk.dart' as sdk;
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.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:pedantic/pedantic.dart';
|
|
||||||
|
|
||||||
import 'chat.dart';
|
class NewGroup extends StatefulWidget {
|
||||||
import 'chat_list.dart';
|
|
||||||
import 'invitation_selection.dart';
|
|
||||||
|
|
||||||
class NewGroupView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: _NewGroup(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _NewGroup extends StatefulWidget {
|
|
||||||
@override
|
@override
|
||||||
_NewGroupState createState() => _NewGroupState();
|
_NewGroupState createState() => _NewGroupState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NewGroupState extends State<_NewGroup> {
|
class _NewGroupState extends State<NewGroup> {
|
||||||
TextEditingController controller = TextEditingController();
|
TextEditingController controller = TextEditingController();
|
||||||
bool publicGroup = false;
|
bool publicGroup = false;
|
||||||
|
|
||||||
@ -45,24 +28,11 @@ class _NewGroupState extends State<_NewGroup> {
|
|||||||
name: controller.text.isNotEmpty ? controller.text : null,
|
name: controller.text.isNotEmpty ? controller.text : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
Navigator.of(context).pop();
|
AdaptivePageLayout.of(context).popUntilIsFirst();
|
||||||
if (roomID != null) {
|
if (roomID != null) {
|
||||||
unawaited(
|
await AdaptivePageLayout.of(context).pushNamed('/rooms/${roomID.result}');
|
||||||
Navigator.of(context).push(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamed('/rooms/${roomID.result}/invite');
|
||||||
context,
|
|
||||||
ChatView(roomID.result),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => InvitationSelection(
|
|
||||||
matrix.client.getRoomById(roomID.result),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +1,20 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
import 'package:fluffychat/utils/fluffy_share.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 'chat.dart';
|
class NewPrivateChat extends StatefulWidget {
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class NewPrivateChatView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: _NewPrivateChat(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _NewPrivateChat extends StatefulWidget {
|
|
||||||
@override
|
@override
|
||||||
_NewPrivateChatState createState() => _NewPrivateChatState();
|
_NewPrivateChatState createState() => _NewPrivateChatState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NewPrivateChatState extends State<_NewPrivateChat> {
|
class _NewPrivateChatState extends State<NewPrivateChat> {
|
||||||
TextEditingController controller = TextEditingController();
|
TextEditingController controller = TextEditingController();
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
bool loading = false;
|
bool loading = false;
|
||||||
@ -59,15 +44,10 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||||||
context: context,
|
context: context,
|
||||||
future: () => user.startDirectChat(),
|
future: () => user.startDirectChat(),
|
||||||
);
|
);
|
||||||
Navigator.of(context).pop();
|
|
||||||
|
|
||||||
if (roomID.error == null) {
|
if (roomID.error == null) {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.popAndPushNamed('/rooms/${roomID.result}');
|
||||||
context,
|
|
||||||
ChatView(roomID.result),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:fluffychat/components/dialogs/bootstrap_dialog.dart';
|
import 'package:fluffychat/components/dialogs/bootstrap_dialog.dart';
|
||||||
import 'package:fluffychat/views/log_view.dart';
|
|
||||||
import 'package:fluffychat/views/settings_3pid.dart';
|
|
||||||
import 'package:fluffychat/views/settings_notifications.dart';
|
|
||||||
import 'package:fluffychat/views/settings_style.dart';
|
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
@ -12,33 +9,16 @@ import 'package:fluffychat/utils/beautify_string_extension.dart';
|
|||||||
import 'package:fluffychat/app_config.dart';
|
import 'package:fluffychat/app_config.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
import 'package:fluffychat/utils/sentry_controller.dart';
|
import 'package:fluffychat/utils/sentry_controller.dart';
|
||||||
import 'package:fluffychat/views/settings_devices.dart';
|
|
||||||
import 'package:fluffychat/views/settings_ignore_list.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:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../components/adaptive_page_layout.dart';
|
|
||||||
import '../components/content_banner.dart';
|
import '../components/content_banner.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import '../utils/app_route.dart';
|
|
||||||
import '../app_config.dart';
|
import '../app_config.dart';
|
||||||
import '../config/setting_keys.dart';
|
import '../config/setting_keys.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
import 'settings_emotes.dart';
|
|
||||||
|
|
||||||
class SettingsView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: Settings(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Settings extends StatefulWidget {
|
class Settings extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
@ -333,12 +313,8 @@ class _SettingsState extends State<Settings> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.notifications_outlined),
|
trailing: Icon(Icons.notifications_outlined),
|
||||||
title: Text(L10n.of(context).notifications),
|
title: Text(L10n.of(context).notifications),
|
||||||
onTap: () async => await Navigator.of(context).push(
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
AppRoute.defaultRoute(
|
.pushNamed('/settings/notifications'),
|
||||||
context,
|
|
||||||
SettingsNotificationsView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
@ -351,12 +327,8 @@ class _SettingsState extends State<Settings> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context).changeTheme),
|
title: Text(L10n.of(context).changeTheme),
|
||||||
onTap: () async => await Navigator.of(context).push(
|
onTap: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/style'),
|
||||||
context,
|
|
||||||
SettingsStyleView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: Icon(Icons.style_outlined),
|
trailing: Icon(Icons.style_outlined),
|
||||||
),
|
),
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
@ -392,12 +364,8 @@ class _SettingsState extends State<Settings> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context).emoteSettings),
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
onTap: () async => await Navigator.of(context).push(
|
onTap: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/emotes'),
|
||||||
context,
|
|
||||||
EmotesSettingsView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: Icon(Icons.insert_emoticon_outlined),
|
trailing: Icon(Icons.insert_emoticon_outlined),
|
||||||
),
|
),
|
||||||
Divider(thickness: 1),
|
Divider(thickness: 1),
|
||||||
@ -425,22 +393,14 @@ class _SettingsState extends State<Settings> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.devices_other_outlined),
|
trailing: Icon(Icons.devices_other_outlined),
|
||||||
title: Text(L10n.of(context).devices),
|
title: Text(L10n.of(context).devices),
|
||||||
onTap: () async => await Navigator.of(context).push(
|
onTap: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/devices'),
|
||||||
context,
|
|
||||||
DevicesSettingsView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.block_outlined),
|
trailing: Icon(Icons.block_outlined),
|
||||||
title: Text(L10n.of(context).ignoredUsers),
|
title: Text(L10n.of(context).ignoredUsers),
|
||||||
onTap: () async => await Navigator.of(context).push(
|
onTap: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/ignore'),
|
||||||
context,
|
|
||||||
SettingsIgnoreListView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.bug_report_outlined),
|
trailing: Icon(Icons.bug_report_outlined),
|
||||||
@ -458,12 +418,8 @@ class _SettingsState extends State<Settings> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.email_outlined),
|
trailing: Icon(Icons.email_outlined),
|
||||||
title: Text(L10n.of(context).passwordRecovery),
|
title: Text(L10n.of(context).passwordRecovery),
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () =>
|
||||||
AppRoute.defaultRoute(
|
AdaptivePageLayout.of(context).pushNamed('/settings/3pid'),
|
||||||
context,
|
|
||||||
Settings3PidView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.exit_to_app_outlined),
|
trailing: Icon(Icons.exit_to_app_outlined),
|
||||||
@ -607,9 +563,7 @@ class _SettingsState extends State<Settings> {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => AdaptivePageLayout.of(context).pushNamed('/logs'),
|
||||||
AppRoute.defaultRoute(context, LogViewer()),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
trailing: Icon(Icons.help_outlined),
|
trailing: Icon(Icons.help_outlined),
|
||||||
|
@ -1,24 +1,10 @@
|
|||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/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 'chat_list.dart';
|
|
||||||
|
|
||||||
class Settings3PidView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: Settings3Pid(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Settings3Pid extends StatefulWidget {
|
class Settings3Pid extends StatefulWidget {
|
||||||
static int sendAttempt = 0;
|
static int sendAttempt = 0;
|
||||||
|
|
||||||
|
@ -4,21 +4,8 @@ import 'package:future_loading_dialog/future_loading_dialog.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 '../components/adaptive_page_layout.dart';
|
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import '../utils/date_time_extension.dart';
|
import '../utils/date_time_extension.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class DevicesSettingsView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: DevicesSettings(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DevicesSettings extends StatefulWidget {
|
class DevicesSettings extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
|
@ -10,26 +10,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
|
||||||
import '../components/adaptive_page_layout.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class EmotesSettingsView extends StatelessWidget {
|
|
||||||
final Room room;
|
|
||||||
final String stateKey;
|
|
||||||
|
|
||||||
EmotesSettingsView({this.room, this.stateKey});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: EmotesSettings(room: room, stateKey: stateKey),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmotesSettings extends StatefulWidget {
|
class EmotesSettings extends StatefulWidget {
|
||||||
final Room room;
|
final Room room;
|
||||||
|
@ -1,23 +1,10 @@
|
|||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/components/avatar.dart';
|
import 'package:fluffychat/components/avatar.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.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 '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class SettingsIgnoreListView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: SettingsIgnoreList(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsIgnoreList extends StatelessWidget {
|
class SettingsIgnoreList extends StatelessWidget {
|
||||||
final controller = TextEditingController();
|
final controller = TextEditingController();
|
||||||
|
@ -1,33 +1,17 @@
|
|||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import '../components/adaptive_page_layout.dart';
|
|
||||||
import '../utils/app_route.dart';
|
|
||||||
import 'chat_list.dart';
|
|
||||||
import 'settings_emotes.dart';
|
|
||||||
|
|
||||||
class MultipleEmotesSettingsView extends StatelessWidget {
|
|
||||||
final Room room;
|
|
||||||
|
|
||||||
MultipleEmotesSettingsView({this.room});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: MultipleEmotesSettings(room: room),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultipleEmotesSettings extends StatelessWidget {
|
class MultipleEmotesSettings extends StatelessWidget {
|
||||||
final Room room;
|
final String roomId;
|
||||||
|
|
||||||
MultipleEmotesSettings({this.room});
|
MultipleEmotesSettings(this.roomId, {Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final room = Matrix.of(context).client.getRoomById(roomId);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(L10n.of(context).emotePacks),
|
title: Text(L10n.of(context).emotePacks),
|
||||||
@ -58,11 +42,9 @@ class MultipleEmotesSettings extends StatelessWidget {
|
|||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(packName),
|
title: Text(packName),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context).pushNamed(
|
||||||
AppRoute.defaultRoute(
|
'/settings/emotes',
|
||||||
context,
|
arguments: room,
|
||||||
EmotesSettingsView(room: room, stateKey: keys[i]),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:fluffychat/app_config.dart';
|
import 'package:fluffychat/app_config.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -11,7 +10,6 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|||||||
import 'package:open_noti_settings/open_noti_settings.dart';
|
import 'package:open_noti_settings/open_noti_settings.dart';
|
||||||
|
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class NotificationSettingsItem {
|
class NotificationSettingsItem {
|
||||||
final PushRuleKind type;
|
final PushRuleKind type;
|
||||||
@ -20,17 +18,6 @@ class NotificationSettingsItem {
|
|||||||
NotificationSettingsItem(this.type, this.key, this.title);
|
NotificationSettingsItem(this.type, this.key, this.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsNotificationsView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: SettingsNotifications(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsNotifications extends StatelessWidget {
|
class SettingsNotifications extends StatelessWidget {
|
||||||
static List<NotificationSettingsItem> items = [
|
static List<NotificationSettingsItem> items = [
|
||||||
NotificationSettingsItem(
|
NotificationSettingsItem(
|
||||||
|
@ -1,25 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:adaptive_theme/adaptive_theme.dart';
|
import 'package:adaptive_theme/adaptive_theme.dart';
|
||||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
|
||||||
import 'package:fluffychat/config/setting_keys.dart';
|
import 'package:fluffychat/config/setting_keys.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:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import 'chat_list.dart';
|
|
||||||
|
|
||||||
class SettingsStyleView extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AdaptivePageLayout(
|
|
||||||
primaryPage: FocusPage.SECOND,
|
|
||||||
firstScaffold: ChatList(),
|
|
||||||
secondScaffold: SettingsStyle(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsStyle extends StatefulWidget {
|
class SettingsStyle extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:file_picker_cross/file_picker_cross.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/login.dart';
|
|
||||||
import 'package:fluffychat/views/sign_up_password.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.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';
|
||||||
@ -61,11 +59,9 @@ class _SignUpState extends State<SignUp> {
|
|||||||
return setState(() => loading = false);
|
return setState(() => loading = false);
|
||||||
}
|
}
|
||||||
setState(() => loading = false);
|
setState(() => loading = false);
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context).pushNamed(
|
||||||
AppRoute(
|
'/signup/password/${Uri.encodeComponent(preferredUsername)}/${Uri.encodeComponent(usernameController.text)}',
|
||||||
SignUpPassword(preferredUsername,
|
arguments: avatar,
|
||||||
avatar: avatar, displayname: usernameController.text),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,9 +167,8 @@ class _SignUpState extends State<SignUp> {
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.of(context).push(
|
onPressed: () =>
|
||||||
AppRoute(Login()),
|
AdaptivePageLayout.of(context).pushNamed('/login'),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
|
||||||
import 'package:flushbar/flushbar_helper.dart';
|
import 'package:flushbar/flushbar_helper.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
|
||||||
import 'package:fluffychat/views/auth_web_view.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 'chat_list.dart';
|
|
||||||
|
|
||||||
class SignUpPassword extends StatefulWidget {
|
class SignUpPassword extends StatefulWidget {
|
||||||
final MatrixFile avatar;
|
final MatrixFile avatar;
|
||||||
final String username;
|
final String username;
|
||||||
@ -69,17 +66,11 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await Navigator.of(context).push(
|
await AdaptivePageLayout.of(context).pushNamed(
|
||||||
AppRoute.defaultRoute(
|
'/authwebview',
|
||||||
|
arguments: () => _signUpAction(
|
||||||
context,
|
context,
|
||||||
AuthWebView(
|
auth: AuthenticationData(session: exception.session),
|
||||||
currentStage,
|
|
||||||
exception.session,
|
|
||||||
() => _signUpAction(
|
|
||||||
context,
|
|
||||||
auth: AuthenticationData(session: exception.session),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -111,9 +102,7 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||||||
.show(context);
|
.show(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Navigator.of(context).pushAndRemoveUntil(
|
if (mounted) setState(() => loading = false);
|
||||||
AppRoute.defaultRoute(context, ChatListView()), (r) => false);
|
|
||||||
setState(() => loading = false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
Loading…
Reference in New Issue
Block a user