Merge pull request #1022 from krille-chan/krille/new-chat-access-settings
design: New chat access settings
This commit is contained in:
commit
5795857b78
11 changed files with 499 additions and 355 deletions
|
|
@ -760,6 +760,9 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"globalChatId": "Global chat ID",
|
||||||
|
"accessAndVisibility": "Access and visibility",
|
||||||
|
"accessAndVisibilityDescription": "Who is allowed to join this chat and how the chat can be discovered.",
|
||||||
"calls": "Calls",
|
"calls": "Calls",
|
||||||
"customEmojisAndStickers": "Custom emojis and stickers",
|
"customEmojisAndStickers": "Custom emojis and stickers",
|
||||||
"customEmojisAndStickersBody": "Add or share custom emojis or stickers which can be used in any chat.",
|
"customEmojisAndStickersBody": "Add or share custom emojis or stickers which can be used in any chat.",
|
||||||
|
|
@ -2276,6 +2279,14 @@
|
||||||
"user": {}
|
"user": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"userWouldLikeToChangeTheChat": "{user} would like to join the chat.",
|
||||||
|
"@userWouldLikeToChangeTheChat": {
|
||||||
|
"placeholders": {
|
||||||
|
"user": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"noPublicLinkHasBeenCreatedYet": "No public link has been created yet",
|
||||||
|
"knock": "Knock",
|
||||||
"users": "Users",
|
"users": "Users",
|
||||||
"@users": {},
|
"@users": {},
|
||||||
"unlockOldMessages": "Unlock old messages",
|
"unlockOldMessages": "Unlock old messages",
|
||||||
|
|
@ -2450,6 +2461,14 @@
|
||||||
"query": {}
|
"query": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"knocking": "Knocking",
|
||||||
|
"chatCanBeDiscoveredViaSearchOnServer": "Chat can be discovered via the search on {server}",
|
||||||
|
"@chatCanBeDiscoveredViaSearchOnServer": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"server": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"searchChatsRooms": "Search for #chats, @users...",
|
"searchChatsRooms": "Search for #chats, @users...",
|
||||||
"@searchChatsRooms": {},
|
"@searchChatsRooms": {},
|
||||||
"nothingFound": "Nothing found...",
|
"nothingFound": "Nothing found...",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart';
|
||||||
import 'package:fluffychat/config/themes.dart';
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:fluffychat/pages/archive/archive.dart';
|
import 'package:fluffychat/pages/archive/archive.dart';
|
||||||
import 'package:fluffychat/pages/chat/chat.dart';
|
import 'package:fluffychat/pages/chat/chat.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_access_settings/chat_access_settings_controller.dart';
|
||||||
import 'package:fluffychat/pages/chat_details/chat_details.dart';
|
import 'package:fluffychat/pages/chat_details/chat_details.dart';
|
||||||
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||||
|
|
@ -344,6 +345,17 @@ abstract class AppRoutes {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
routes: [
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: 'access',
|
||||||
|
pageBuilder: (context, state) => defaultPageBuilder(
|
||||||
|
context,
|
||||||
|
state,
|
||||||
|
ChatAccessSettings(
|
||||||
|
roomId: state.pathParameters['roomid']!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
redirect: loggedOutRedirect,
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'members',
|
path: 'members',
|
||||||
pageBuilder: (context, state) => defaultPageBuilder(
|
pageBuilder: (context, state) => defaultPageBuilder(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
import 'package:flutter/material.dart' hide Visibility;
|
||||||
|
|
||||||
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/pages/chat_access_settings/chat_access_settings_page.dart';
|
||||||
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||||
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
|
|
||||||
|
class ChatAccessSettings extends StatefulWidget {
|
||||||
|
final String roomId;
|
||||||
|
const ChatAccessSettings({required this.roomId, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChatAccessSettings> createState() => ChatAccessSettingsController();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatAccessSettingsController extends State<ChatAccessSettings> {
|
||||||
|
bool joinRulesLoading = false;
|
||||||
|
bool visibilityLoading = false;
|
||||||
|
bool historyVisibilityLoading = false;
|
||||||
|
bool guestAccessLoading = false;
|
||||||
|
Room get room => Matrix.of(context).client.getRoomById(widget.roomId)!;
|
||||||
|
|
||||||
|
void setJoinRule(JoinRules? newJoinRules) async {
|
||||||
|
if (newJoinRules == null) return;
|
||||||
|
setState(() {
|
||||||
|
joinRulesLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await room.setJoinRules(newJoinRules);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to change join rules', e, s);
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
e.toLocalizedString(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
joinRulesLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHistoryVisibility(HistoryVisibility? historyVisibility) async {
|
||||||
|
if (historyVisibility == null) return;
|
||||||
|
setState(() {
|
||||||
|
historyVisibilityLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await room.setHistoryVisibility(historyVisibility);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to change history visibility', e, s);
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
e.toLocalizedString(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
historyVisibilityLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGuestAccess(GuestAccess? guestAccess) async {
|
||||||
|
if (guestAccess == null) return;
|
||||||
|
setState(() {
|
||||||
|
guestAccessLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await room.setGuestAccess(guestAccess);
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to change guest access', e, s);
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
e.toLocalizedString(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
guestAccessLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRoomAction() async {
|
||||||
|
final roomVersion = room
|
||||||
|
.getState(EventTypes.RoomCreate)!
|
||||||
|
.content
|
||||||
|
.tryGet<String>('room_version');
|
||||||
|
final capabilitiesResult = await showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => room.client.getCapabilities(),
|
||||||
|
);
|
||||||
|
final capabilities = capabilitiesResult.result;
|
||||||
|
if (capabilities == null) return;
|
||||||
|
final newVersion = await showConfirmationDialog<String>(
|
||||||
|
context: context,
|
||||||
|
title: L10n.of(context)!.replaceRoomWithNewerVersion,
|
||||||
|
actions: capabilities.mRoomVersions!.available.entries
|
||||||
|
.where((r) => r.key != roomVersion)
|
||||||
|
.map(
|
||||||
|
(version) => AlertDialogAction(
|
||||||
|
key: version.key,
|
||||||
|
label:
|
||||||
|
'${version.key} (${version.value.toString().split('.').last})',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
if (newVersion == null ||
|
||||||
|
OkCancelResult.cancel ==
|
||||||
|
await showOkCancelAlertDialog(
|
||||||
|
useRootNavigator: false,
|
||||||
|
context: context,
|
||||||
|
okLabel: L10n.of(context)!.yes,
|
||||||
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
|
title: L10n.of(context)!.areYouSure,
|
||||||
|
message: L10n.of(context)!.roomUpgradeDescription,
|
||||||
|
isDestructiveAction: true,
|
||||||
|
)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => room.client.upgradeRoom(room.id, newVersion),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCanonicalAlias() async {
|
||||||
|
final input = await showTextInputDialog(
|
||||||
|
context: context,
|
||||||
|
title: L10n.of(context)!.editRoomAliases,
|
||||||
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
|
okLabel: L10n.of(context)!.ok,
|
||||||
|
textFields: [
|
||||||
|
DialogTextField(
|
||||||
|
prefixText: '#',
|
||||||
|
suffixText: room.client.userID!.domain!,
|
||||||
|
initialText: room.canonicalAlias.localpart,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final newAliasLocalpart = input?.singleOrNull?.trim();
|
||||||
|
if (newAliasLocalpart == null || newAliasLocalpart.isEmpty) return;
|
||||||
|
|
||||||
|
await showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => room.setCanonicalAlias(
|
||||||
|
'#$newAliasLocalpart:${room.client.userID!.domain!}',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChatVisibilityOnDirectory(bool? visibility) async {
|
||||||
|
if (visibility == null) return;
|
||||||
|
setState(() {
|
||||||
|
visibilityLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await room.client.setRoomVisibilityOnDirectory(
|
||||||
|
room.id,
|
||||||
|
visibility: visibility == true ? Visibility.public : Visibility.private,
|
||||||
|
);
|
||||||
|
setState(() {});
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to change visibility', e, s);
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
e.toLocalizedString(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
visibilityLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChatAccessSettingsPageView(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
172
lib/pages/chat_access_settings/chat_access_settings_page.dart
Normal file
172
lib/pages/chat_access_settings/chat_access_settings_page.dart
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
import 'package:flutter/material.dart' hide Visibility;
|
||||||
|
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/pages/chat_access_settings/chat_access_settings_controller.dart';
|
||||||
|
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||||
|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||||
|
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||||
|
|
||||||
|
class ChatAccessSettingsPageView extends StatelessWidget {
|
||||||
|
final ChatAccessSettingsController controller;
|
||||||
|
const ChatAccessSettingsPageView(this.controller, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final room = controller.room;
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: const Center(child: BackButton()),
|
||||||
|
title: Text(L10n.of(context)!.accessAndVisibility),
|
||||||
|
),
|
||||||
|
body: MaxWidthBody(
|
||||||
|
child: StreamBuilder<Object>(
|
||||||
|
stream: room.onUpdate.stream,
|
||||||
|
builder: (context, snapshot) => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context)!.visibilityOfTheChatHistory,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final historyVisibility in HistoryVisibility.values)
|
||||||
|
RadioListTile<HistoryVisibility>.adaptive(
|
||||||
|
title: Text(
|
||||||
|
historyVisibility
|
||||||
|
.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
||||||
|
),
|
||||||
|
value: historyVisibility,
|
||||||
|
groupValue: room.historyVisibility,
|
||||||
|
onChanged: controller.historyVisibilityLoading ||
|
||||||
|
!room.canChangeHistoryVisibility
|
||||||
|
? null
|
||||||
|
: controller.setHistoryVisibility,
|
||||||
|
),
|
||||||
|
Divider(color: Theme.of(context).dividerColor),
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context)!.whoIsAllowedToJoinThisGroup,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final joinRule in JoinRules.values)
|
||||||
|
RadioListTile<JoinRules>.adaptive(
|
||||||
|
title: Text(
|
||||||
|
joinRule
|
||||||
|
.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
||||||
|
),
|
||||||
|
value: joinRule,
|
||||||
|
groupValue: room.joinRules,
|
||||||
|
onChanged:
|
||||||
|
controller.joinRulesLoading || !room.canChangeJoinRules
|
||||||
|
? null
|
||||||
|
: controller.setJoinRule,
|
||||||
|
),
|
||||||
|
Divider(color: Theme.of(context).dividerColor),
|
||||||
|
if ({JoinRules.public, JoinRules.knock}
|
||||||
|
.contains(room.joinRules)) ...[
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context)!.areGuestsAllowedToJoin,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final guestAccess in GuestAccess.values)
|
||||||
|
RadioListTile<GuestAccess>.adaptive(
|
||||||
|
title: Text(
|
||||||
|
guestAccess
|
||||||
|
.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
||||||
|
),
|
||||||
|
value: guestAccess,
|
||||||
|
groupValue: room.guestAccess,
|
||||||
|
onChanged: controller.guestAccessLoading ||
|
||||||
|
!room.canChangeGuestAccess
|
||||||
|
? null
|
||||||
|
: controller.setGuestAccess,
|
||||||
|
),
|
||||||
|
Divider(color: Theme.of(context).dividerColor),
|
||||||
|
FutureBuilder(
|
||||||
|
future: room.client.getRoomVisibilityOnDirectory(room.id),
|
||||||
|
builder: (context, snapshot) => SwitchListTile.adaptive(
|
||||||
|
value: snapshot.data == Visibility.public,
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context)!.chatCanBeDiscoveredViaSearchOnServer(
|
||||||
|
room.client.userID!.domain!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: controller.setChatVisibilityOnDirectory,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.of(context)!.publicLink),
|
||||||
|
subtitle: room.canonicalAlias.isEmpty
|
||||||
|
? Text(
|
||||||
|
L10n.of(context)!.noPublicLinkHasBeenCreatedYet,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
|
'https://matrix.to/#/${room.canonicalAlias}',
|
||||||
|
style: TextStyle(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: room.canChangeStateEvent(EventTypes.RoomCanonicalAlias)
|
||||||
|
? controller.setCanonicalAlias
|
||||||
|
: null,
|
||||||
|
trailing: room.canonicalAlias.isEmpty
|
||||||
|
? const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Icon(Icons.add),
|
||||||
|
)
|
||||||
|
: IconButton(
|
||||||
|
icon: Icon(Icons.adaptive.share_outlined),
|
||||||
|
onPressed: () => FluffyShare.share(room.id, context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.of(context)!.globalChatId),
|
||||||
|
subtitle: SelectableText(room.id),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.copy_outlined),
|
||||||
|
onPressed: () => FluffyShare.share(room.id, context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.of(context)!.roomVersion),
|
||||||
|
subtitle: SelectableText(
|
||||||
|
room
|
||||||
|
.getState(EventTypes.RoomCreate)!
|
||||||
|
.content
|
||||||
|
.tryGet<String>('room_version') ??
|
||||||
|
'Unknown',
|
||||||
|
),
|
||||||
|
trailing: room.canSendEvent(EventTypes.RoomTombstone)
|
||||||
|
? IconButton(
|
||||||
|
icon: const Icon(Icons.upgrade_outlined),
|
||||||
|
onPressed: controller.updateRoomAction,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
@ -8,7 +7,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:matrix/matrix.dart' as matrix;
|
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
|
import 'package:fluffychat/pages/chat_details/chat_details_view.dart';
|
||||||
|
|
@ -71,116 +69,6 @@ class ChatDetailsController extends State<ChatDetails> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editAliases() async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!);
|
|
||||||
|
|
||||||
final aliasesResult = await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room!.client.getLocalAliases(room.id),
|
|
||||||
);
|
|
||||||
|
|
||||||
final aliases = aliasesResult.result;
|
|
||||||
|
|
||||||
if (aliases == null) return;
|
|
||||||
final adminMode = room!.canSendEvent(EventTypes.RoomCanonicalAlias);
|
|
||||||
if (aliases.isEmpty && (room.canonicalAlias.isNotEmpty)) {
|
|
||||||
aliases.add(room.canonicalAlias);
|
|
||||||
}
|
|
||||||
if (aliases.isEmpty && adminMode) {
|
|
||||||
return setAliasAction();
|
|
||||||
}
|
|
||||||
final select = await showConfirmationDialog(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.editRoomAliases,
|
|
||||||
actions: [
|
|
||||||
if (adminMode)
|
|
||||||
AlertDialogAction(label: L10n.of(context)!.create, key: 'new'),
|
|
||||||
...aliases.map((alias) => AlertDialogAction(key: alias, label: alias)),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (select == null) return;
|
|
||||||
if (select == 'new') {
|
|
||||||
return setAliasAction();
|
|
||||||
}
|
|
||||||
final option = await showConfirmationDialog<AliasActions>(
|
|
||||||
context: context,
|
|
||||||
title: select,
|
|
||||||
actions: [
|
|
||||||
AlertDialogAction(
|
|
||||||
label: L10n.of(context)!.copyToClipboard,
|
|
||||||
key: AliasActions.copy,
|
|
||||||
isDefaultAction: true,
|
|
||||||
),
|
|
||||||
if (adminMode) ...{
|
|
||||||
AlertDialogAction(
|
|
||||||
label: L10n.of(context)!.setAsCanonicalAlias,
|
|
||||||
key: AliasActions.setCanonical,
|
|
||||||
isDestructiveAction: true,
|
|
||||||
),
|
|
||||||
AlertDialogAction(
|
|
||||||
label: L10n.of(context)!.delete,
|
|
||||||
key: AliasActions.delete,
|
|
||||||
isDestructiveAction: true,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (option == null) return;
|
|
||||||
switch (option) {
|
|
||||||
case AliasActions.copy:
|
|
||||||
await Clipboard.setData(ClipboardData(text: select));
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text(L10n.of(context)!.copiedToClipboard)),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case AliasActions.delete:
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.client.deleteRoomAlias(select),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case AliasActions.setCanonical:
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.client.setRoomStateWithKey(
|
|
||||||
room.id,
|
|
||||||
EventTypes.RoomCanonicalAlias,
|
|
||||||
'',
|
|
||||||
{
|
|
||||||
'alias': select,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAliasAction() async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
|
||||||
final domain = room.client.userID!.domain;
|
|
||||||
|
|
||||||
final input = await showTextInputDialog(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.setInvitationLink,
|
|
||||||
okLabel: L10n.of(context)!.ok,
|
|
||||||
cancelLabel: L10n.of(context)!.cancel,
|
|
||||||
textFields: [
|
|
||||||
DialogTextField(
|
|
||||||
prefixText: '#',
|
|
||||||
suffixText: domain,
|
|
||||||
hintText: L10n.of(context)!.alias,
|
|
||||||
initialText: room.canonicalAlias.localpart,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (input == null) return;
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () =>
|
|
||||||
room.client.setRoomAlias('#${input.single}:${domain!}', room.id),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTopicAction() async {
|
void setTopicAction() async {
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||||
final input = await showTextInputDialog(
|
final input = await showTextInputDialog(
|
||||||
|
|
@ -211,91 +99,6 @@ class ChatDetailsController extends State<ChatDetails> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGuestAccess() async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
|
||||||
final currentGuestAccess = room.guestAccess;
|
|
||||||
final newGuestAccess = await showConfirmationDialog<GuestAccess>(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.areGuestsAllowedToJoin,
|
|
||||||
actions: GuestAccess.values
|
|
||||||
.map(
|
|
||||||
(guestAccess) => AlertDialogAction(
|
|
||||||
key: guestAccess,
|
|
||||||
label: guestAccess
|
|
||||||
.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
|
||||||
isDefaultAction: guestAccess == currentGuestAccess,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
if (newGuestAccess == null || newGuestAccess == currentGuestAccess) return;
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.setGuestAccess(newGuestAccess),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHistoryVisibility() async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
|
||||||
final currentHistoryVisibility = room.historyVisibility;
|
|
||||||
final newHistoryVisibility =
|
|
||||||
await showConfirmationDialog<HistoryVisibility>(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.visibilityOfTheChatHistory,
|
|
||||||
actions: HistoryVisibility.values
|
|
||||||
.map(
|
|
||||||
(visibility) => AlertDialogAction(
|
|
||||||
key: visibility,
|
|
||||||
label: visibility
|
|
||||||
.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
|
||||||
isDefaultAction: visibility == currentHistoryVisibility,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
if (newHistoryVisibility == null ||
|
|
||||||
newHistoryVisibility == currentHistoryVisibility) return;
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.setHistoryVisibility(newHistoryVisibility),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setJoinRules() async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
|
||||||
final currentJoinRule = room.joinRules;
|
|
||||||
final newJoinRule = await showConfirmationDialog<JoinRules>(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.whoIsAllowedToJoinThisGroup,
|
|
||||||
actions: JoinRules.values
|
|
||||||
.map(
|
|
||||||
(joinRule) => AlertDialogAction(
|
|
||||||
key: joinRule,
|
|
||||||
label:
|
|
||||||
joinRule.getLocalizedString(MatrixLocals(L10n.of(context)!)),
|
|
||||||
isDefaultAction: joinRule == currentJoinRule,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
if (newJoinRule == null || newJoinRule == currentJoinRule) return;
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () async {
|
|
||||||
await room.setJoinRules(newJoinRule);
|
|
||||||
room.client.setRoomVisibilityOnDirectory(
|
|
||||||
roomId!,
|
|
||||||
visibility: {
|
|
||||||
JoinRules.public,
|
|
||||||
JoinRules.knock,
|
|
||||||
}.contains(newJoinRule)
|
|
||||||
? matrix.Visibility.public
|
|
||||||
: matrix.Visibility.private,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void goToEmoteSettings() async {
|
void goToEmoteSettings() async {
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||||
// okay, we need to test if there are any emote state events other than the default one
|
// okay, we need to test if there are any emote state events other than the default one
|
||||||
|
|
|
||||||
|
|
@ -267,23 +267,6 @@ class ChatDetailsView extends StatelessWidget {
|
||||||
height: 1,
|
height: 1,
|
||||||
color: Theme.of(context).dividerColor,
|
color: Theme.of(context).dividerColor,
|
||||||
),
|
),
|
||||||
if (room.joinRules == JoinRules.public)
|
|
||||||
ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: iconColor,
|
|
||||||
child: const Icon(Icons.link_outlined),
|
|
||||||
),
|
|
||||||
trailing: const Icon(Icons.chevron_right_outlined),
|
|
||||||
onTap: controller.editAliases,
|
|
||||||
title: Text(L10n.of(context)!.editRoomAliases),
|
|
||||||
subtitle: Text(
|
|
||||||
(room.canonicalAlias.isNotEmpty)
|
|
||||||
? room.canonicalAlias
|
|
||||||
: L10n.of(context)!.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
|
|
@ -308,69 +291,14 @@ class ChatDetailsView extends StatelessWidget {
|
||||||
child: const Icon(Icons.shield_outlined),
|
child: const Icon(Icons.shield_outlined),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
L10n.of(context)!.whoIsAllowedToJoinThisGroup,
|
L10n.of(context)!.accessAndVisibility,
|
||||||
),
|
|
||||||
trailing: room.canChangeJoinRules
|
|
||||||
? const Icon(Icons.chevron_right_outlined)
|
|
||||||
: null,
|
|
||||||
subtitle: Text(
|
|
||||||
room.joinRules?.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)!),
|
|
||||||
) ??
|
|
||||||
L10n.of(context)!.none,
|
|
||||||
),
|
|
||||||
onTap: room.canChangeJoinRules
|
|
||||||
? controller.setJoinRules
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
if (!room.isDirectChat)
|
|
||||||
ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: iconColor,
|
|
||||||
child: const Icon(Icons.visibility_outlined),
|
|
||||||
),
|
|
||||||
trailing: room.canChangeHistoryVisibility
|
|
||||||
? const Icon(Icons.chevron_right_outlined)
|
|
||||||
: null,
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context)!.visibilityOfTheChatHistory,
|
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
room.historyVisibility?.getLocalizedString(
|
L10n.of(context)!.accessAndVisibilityDescription,
|
||||||
MatrixLocals(L10n.of(context)!),
|
|
||||||
) ??
|
|
||||||
L10n.of(context)!.none,
|
|
||||||
),
|
),
|
||||||
onTap: room.canChangeHistoryVisibility
|
onTap: () => context
|
||||||
? controller.setHistoryVisibility
|
.push('/rooms/${room.id}/details/access'),
|
||||||
: null,
|
trailing: const Icon(Icons.chevron_right_outlined),
|
||||||
),
|
|
||||||
if (room.joinRules == JoinRules.public)
|
|
||||||
ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: iconColor,
|
|
||||||
child: const Icon(
|
|
||||||
Icons.person_add_alt_1_outlined,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: room.canChangeGuestAccess
|
|
||||||
? const Icon(Icons.chevron_right_outlined)
|
|
||||||
: null,
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context)!.areGuestsAllowedToJoin,
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
room.guestAccess.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context)!),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: room.canChangeGuestAccess
|
|
||||||
? controller.setGuestAccess
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
if (!room.isDirectChat)
|
if (!room.isDirectChat)
|
||||||
ListTile(
|
ListTile(
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,14 @@ class ParticipantListItem extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final membershipBatch = <Membership, String>{
|
final membershipBatch = switch (user.membership) {
|
||||||
Membership.join: '',
|
Membership.ban => L10n.of(context)!.banned,
|
||||||
Membership.ban: L10n.of(context)!.banned,
|
Membership.invite => L10n.of(context)!.invited,
|
||||||
Membership.invite: L10n.of(context)!.invited,
|
Membership.join => null,
|
||||||
Membership.leave: L10n.of(context)!.leftTheChat,
|
Membership.knock => L10n.of(context)!.knocking,
|
||||||
|
Membership.leave => L10n.of(context)!.leftTheChat,
|
||||||
};
|
};
|
||||||
|
|
||||||
final permissionBatch = user.powerLevel == 100
|
final permissionBatch = user.powerLevel == 100
|
||||||
? L10n.of(context)!.admin
|
? L10n.of(context)!.admin
|
||||||
: user.powerLevel >= 50
|
: user.powerLevel >= 50
|
||||||
|
|
@ -66,7 +68,7 @@ class ParticipantListItem extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
membershipBatch[user.membership]!.isEmpty
|
membershipBatch == null
|
||||||
? const SizedBox.shrink()
|
? const SizedBox.shrink()
|
||||||
: Container(
|
: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
|
|
@ -75,8 +77,7 @@ class ParticipantListItem extends StatelessWidget {
|
||||||
color: Theme.of(context).secondaryHeaderColor,
|
color: Theme.of(context).secondaryHeaderColor,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child:
|
child: Center(child: Text(membershipBatch)),
|
||||||
Center(child: Text(membershipBatch[user.membership]!)),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:adaptive_dialog/adaptive_dialog.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:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
@ -71,44 +70,6 @@ class ChatPermissionsSettingsController extends State<ChatPermissionsSettings> {
|
||||||
false),
|
false),
|
||||||
);
|
);
|
||||||
|
|
||||||
void updateRoomAction(Capabilities capabilities) async {
|
|
||||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
|
||||||
final roomVersion = room
|
|
||||||
.getState(EventTypes.RoomCreate)!
|
|
||||||
.content['room_version'] as String? ??
|
|
||||||
'1';
|
|
||||||
final newVersion = await showConfirmationDialog<String>(
|
|
||||||
context: context,
|
|
||||||
title: L10n.of(context)!.replaceRoomWithNewerVersion,
|
|
||||||
actions: capabilities.mRoomVersions!.available.entries
|
|
||||||
.where((r) => r.key != roomVersion)
|
|
||||||
.map(
|
|
||||||
(version) => AlertDialogAction(
|
|
||||||
key: version.key,
|
|
||||||
label:
|
|
||||||
'${version.key} (${version.value.toString().split('.').last})',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
if (newVersion == null ||
|
|
||||||
OkCancelResult.cancel ==
|
|
||||||
await showOkCancelAlertDialog(
|
|
||||||
useRootNavigator: false,
|
|
||||||
context: context,
|
|
||||||
okLabel: L10n.of(context)!.yes,
|
|
||||||
cancelLabel: L10n.of(context)!.cancel,
|
|
||||||
title: L10n.of(context)!.areYouSure,
|
|
||||||
message: L10n.of(context)!.roomUpgradeDescription,
|
|
||||||
)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await showFutureLoadingDialog(
|
|
||||||
context: context,
|
|
||||||
future: () => room.client.upgradeRoom(roomId!, newVersion),
|
|
||||||
).then((_) => context.pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => ChatPermissionsSettingsView(this);
|
Widget build(BuildContext context) => ChatPermissionsSettingsView(this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
||||||
entry.value,
|
entry.value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(thickness: 1),
|
Divider(color: Theme.of(context).dividerColor),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
L10n.of(context)!.notifications,
|
L10n.of(context)!.notifications,
|
||||||
|
|
@ -87,7 +87,7 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Divider(thickness: 1),
|
Divider(color: Theme.of(context).dividerColor),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
L10n.of(context)!.configureChat,
|
L10n.of(context)!.configureChat,
|
||||||
|
|
@ -109,33 +109,6 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
||||||
category: 'events',
|
category: 'events',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (room.canSendEvent(EventTypes.RoomTombstone)) ...{
|
|
||||||
const Divider(thickness: 1),
|
|
||||||
FutureBuilder<Capabilities>(
|
|
||||||
future: room.client.getCapabilities(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator.adaptive(
|
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final roomVersion = room
|
|
||||||
.getState(EventTypes.RoomCreate)!
|
|
||||||
.content['room_version'] as String? ??
|
|
||||||
'1';
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
'${L10n.of(context)!.roomVersion}: $roomVersion',
|
|
||||||
),
|
|
||||||
onTap: () =>
|
|
||||||
controller.updateRoomAction(snapshot.data!),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||||
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||||
import 'package:fluffychat/utils/url_launcher.dart';
|
import 'package:fluffychat/utils/url_launcher.dart';
|
||||||
|
|
@ -105,6 +107,57 @@ class UserBottomSheetView extends StatelessWidget {
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
|
if (user?.membership == Membership.knock)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: Material(
|
||||||
|
color: Theme.of(context).colorScheme.tertiaryContainer,
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
|
child: ListTile(
|
||||||
|
minVerticalPadding: 16,
|
||||||
|
title: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12.0),
|
||||||
|
child: Text(
|
||||||
|
L10n.of(context)!
|
||||||
|
.userWouldLikeToChangeTheChat(displayname),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Row(
|
||||||
|
children: [
|
||||||
|
TextButton.icon(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.background,
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
onPressed: () => showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => user!.room.invite(user.id),
|
||||||
|
),
|
||||||
|
icon: const Icon(Icons.check_outlined),
|
||||||
|
label: Text(L10n.of(context)!.accept),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
TextButton.icon(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.errorContainer,
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).colorScheme.onErrorContainer,
|
||||||
|
),
|
||||||
|
onPressed: () => showFutureLoadingDialog(
|
||||||
|
context: context,
|
||||||
|
future: () => user!.room.kick(user.id),
|
||||||
|
),
|
||||||
|
icon: const Icon(Icons.cancel_outlined),
|
||||||
|
label: Text(L10n.of(context)!.decline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|
|
||||||
|
|
@ -31,22 +31,26 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
||||||
void _joinRoom(BuildContext context) async {
|
void _joinRoom(BuildContext context) async {
|
||||||
final client = Matrix.of(outerContext).client;
|
final client = Matrix.of(outerContext).client;
|
||||||
final chunk = this.chunk;
|
final chunk = this.chunk;
|
||||||
|
final knock = chunk?.joinRule == 'knock';
|
||||||
final result = await showFutureLoadingDialog<String>(
|
final result = await showFutureLoadingDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
if (chunk != null && client.getRoomById(chunk.roomId) != null) {
|
if (chunk != null && client.getRoomById(chunk.roomId) != null) {
|
||||||
return chunk.roomId;
|
return chunk.roomId;
|
||||||
}
|
}
|
||||||
final roomId = chunk != null && chunk.joinRule == 'knock'
|
final roomId = chunk != null && knock
|
||||||
? await client.knockRoom(chunk.roomId)
|
? await client.knockRoom(chunk.roomId)
|
||||||
: await client.joinRoom(roomAlias ?? chunk!.roomId);
|
: await client.joinRoom(roomAlias ?? chunk!.roomId);
|
||||||
|
|
||||||
if (client.getRoomById(roomId) == null) {
|
if (!knock && client.getRoomById(roomId) == null) {
|
||||||
await client.waitForRoomInSync(roomId);
|
await client.waitForRoomInSync(roomId);
|
||||||
}
|
}
|
||||||
return roomId;
|
return roomId;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
if (knock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (result.error == null) {
|
if (result.error == null) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
// don't open the room if the joined room is a space
|
// don't open the room if the joined room is a space
|
||||||
|
|
@ -138,9 +142,11 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
||||||
child: ElevatedButton.icon(
|
child: ElevatedButton.icon(
|
||||||
onPressed: () => _joinRoom(context),
|
onPressed: () => _joinRoom(context),
|
||||||
label: Text(
|
label: Text(
|
||||||
chunk?.roomType == 'm.space'
|
chunk?.joinRule == 'knock'
|
||||||
? L10n.of(context)!.joinSpace
|
? L10n.of(context)!.knock
|
||||||
: L10n.of(context)!.joinRoom,
|
: chunk?.roomType == 'm.space'
|
||||||
|
? L10n.of(context)!.joinSpace
|
||||||
|
: L10n.of(context)!.joinRoom,
|
||||||
),
|
),
|
||||||
icon: const Icon(Icons.login_outlined),
|
icon: const Icon(Icons.login_outlined),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue