You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
8.4 KiB
Dart
297 lines
8.4 KiB
Dart
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_page.dart';
|
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart';
|
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
|
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
|
import 'package:fluffychat/widgets/future_loading_dialog.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)!;
|
|
|
|
String get roomVersion =>
|
|
room
|
|
.getState(EventTypes.RoomCreate)!
|
|
.content
|
|
.tryGet<String>('room_version') ??
|
|
'Unknown';
|
|
|
|
/// Calculates which join rules are available based on the information on
|
|
/// https://spec.matrix.org/v1.11/rooms/#feature-matrix
|
|
List<JoinRules> get availableJoinRules {
|
|
final joinRules = Set<JoinRules>.from(JoinRules.values);
|
|
|
|
final roomVersionInt = int.tryParse(roomVersion);
|
|
|
|
// Knock is only supported for rooms up from version 7:
|
|
if (roomVersionInt != null && roomVersionInt <= 6) {
|
|
joinRules.remove(JoinRules.knock);
|
|
}
|
|
|
|
// Not yet supported in FluffyChat:
|
|
joinRules.remove(JoinRules.restricted);
|
|
joinRules.remove(JoinRules.knockRestricted);
|
|
|
|
// If an unsupported join rule is the current join rule, display it:
|
|
final currentJoinRule = room.joinRules;
|
|
if (currentJoinRule != null) joinRules.add(currentJoinRule);
|
|
|
|
return joinRules.toList();
|
|
}
|
|
|
|
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 showModalActionPopup<String>(
|
|
context: context,
|
|
title: L10n.of(context).replaceRoomWithNewerVersion,
|
|
cancelLabel: L10n.of(context).cancel,
|
|
actions: capabilities.mRoomVersions!.available.entries
|
|
.where((r) => r.key != roomVersion)
|
|
.map(
|
|
(version) => AdaptiveModalAction(
|
|
value: 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,
|
|
isDestructive: true,
|
|
)) {
|
|
return;
|
|
}
|
|
await showFutureLoadingDialog(
|
|
context: context,
|
|
future: () => room.client.upgradeRoom(room.id, newVersion),
|
|
);
|
|
}
|
|
|
|
Future<void> addAlias() async {
|
|
final domain = room.client.userID?.domain;
|
|
if (domain == null) {
|
|
throw Exception('userID or domain is null! This should never happen.');
|
|
}
|
|
|
|
final input = await showTextInputDialog(
|
|
context: context,
|
|
title: L10n.of(context).editRoomAliases,
|
|
prefixText: '#',
|
|
suffixText: domain,
|
|
hintText: L10n.of(context).alias,
|
|
);
|
|
final aliasLocalpart = input?.trim();
|
|
if (aliasLocalpart == null || aliasLocalpart.isEmpty) return;
|
|
final alias = '#$aliasLocalpart:$domain';
|
|
|
|
final result = await showFutureLoadingDialog(
|
|
context: context,
|
|
future: () => room.client.setRoomAlias(alias, room.id),
|
|
);
|
|
if (result.error != null) return;
|
|
setState(() {});
|
|
|
|
if (!room.canChangeStateEvent(EventTypes.RoomCanonicalAlias)) return;
|
|
|
|
final canonicalAliasConsent = await showOkCancelAlertDialog(
|
|
context: context,
|
|
title: L10n.of(context).setAsCanonicalAlias,
|
|
message: alias,
|
|
okLabel: L10n.of(context).yes,
|
|
cancelLabel: L10n.of(context).no,
|
|
);
|
|
|
|
final altAliases = room
|
|
.getState(EventTypes.RoomCanonicalAlias)
|
|
?.content
|
|
.tryGetList<String>('alt_aliases')
|
|
?.toSet() ??
|
|
{};
|
|
if (room.canonicalAlias.isNotEmpty) altAliases.add(room.canonicalAlias);
|
|
altAliases.add(alias);
|
|
if (canonicalAliasConsent == OkCancelResult.ok) {
|
|
altAliases.remove(alias);
|
|
} else {
|
|
altAliases.remove(room.canonicalAlias);
|
|
}
|
|
|
|
await showFutureLoadingDialog(
|
|
context: context,
|
|
future: () => room.client.setRoomStateWithKey(
|
|
room.id,
|
|
EventTypes.RoomCanonicalAlias,
|
|
'',
|
|
{
|
|
'alias': canonicalAliasConsent == OkCancelResult.ok
|
|
? alias
|
|
: room.canonicalAlias,
|
|
if (altAliases.isNotEmpty) 'alt_aliases': altAliases.toList(),
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
void deleteAlias(String alias) async {
|
|
await showFutureLoadingDialog(
|
|
context: context,
|
|
future: () => room.client.deleteRoomAlias(alias),
|
|
);
|
|
setState(() {});
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|