fluffychat merge
This commit is contained in:
commit
0cb6fe6daf
34 changed files with 1124 additions and 590 deletions
|
|
@ -2616,5 +2616,7 @@
|
|||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"noDatabaseEncryption": "تشفير قاعدة البيانات غير مدعوم على هذا النظام الأساسي",
|
||||
"@noDatabaseEncryption": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2586,5 +2586,95 @@
|
|||
}
|
||||
},
|
||||
"verifyOtherDeviceDescription": "Wenn Sie ein anderes Gerät verifizieren, können diese Geräteschlüssel austauschen, was Ihre Sicherheit insgesamt erhöht. 💪 Wenn Sie eine Verifizierung starten, erscheint ein Pop-up in der App auf beiden Geräten. Dort sehen Sie dann eine Reihe von Emojis oder Zahlen, die Sie miteinander vergleichen müssen. Am besten hältst du beide Geräte bereit, bevor du die Verifizierung startest. 🤳",
|
||||
"@verifyOtherDeviceDescription": {}
|
||||
"@verifyOtherDeviceDescription": {},
|
||||
"presenceStyle": "Statusmeldungen:",
|
||||
"@presenceStyle": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"presencesToggle": "Status-Nachrichten anderer Benutzer anzeigen",
|
||||
"@presencesToggle": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"incomingMessages": "Eingehende Nachrichten",
|
||||
"@incomingMessages": {},
|
||||
"commandHint_unignore": "Angegebene Matrix-ID nicht mehr ignorieren",
|
||||
"@commandHint_unignore": {},
|
||||
"commandHint_ignore": "Angegebene Matrix-ID ignorieren",
|
||||
"@commandHint_ignore": {},
|
||||
"noDatabaseEncryption": "Datenbankverschlüsselung wird auf dieser Plattform nicht unterstützt",
|
||||
"@noDatabaseEncryption": {},
|
||||
"hidePresences": "Status-Liste verbergen?",
|
||||
"@hidePresences": {},
|
||||
"stickers": "Sticker",
|
||||
"@stickers": {},
|
||||
"discover": "Entdecken",
|
||||
"@discover": {},
|
||||
"unreadChatsInApp": "{appname}: {unread} ungelesene Chats",
|
||||
"@unreadChatsInApp": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
},
|
||||
"customEmojisAndStickersBody": "Eigene Emojis oder Sticker zur Nutzung im Chat hinzufügen oder teilen.",
|
||||
"@customEmojisAndStickersBody": {},
|
||||
"globalChatId": "Globale Chat-ID",
|
||||
"@globalChatId": {},
|
||||
"accessAndVisibility": "Zugang und Sichtbarkeit",
|
||||
"@accessAndVisibility": {},
|
||||
"hideMemberChangesInPublicChats": "Mitglieder-Änderungen in öffentlichen Chats ausblenden",
|
||||
"@hideMemberChangesInPublicChats": {},
|
||||
"accessAndVisibilityDescription": "Wer darf dem Chat beitreten und wie kann der Chat gefunden werden.",
|
||||
"@accessAndVisibilityDescription": {},
|
||||
"hideMemberChangesInPublicChatsBody": "Zeige keine Beitritt- oder Verlassen-Ereignisse von Mitgliedern in der Timeline an, um die Lesbarkeit in öffentlichen Chats zu verbessern.",
|
||||
"@hideMemberChangesInPublicChatsBody": {},
|
||||
"userWouldLikeToChangeTheChat": "{user} würde dem Chat gerne beitreten.",
|
||||
"@userWouldLikeToChangeTheChat": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"noPublicLinkHasBeenCreatedYet": "Es wurde noch kein öffentlicher Link erstellt",
|
||||
"@noPublicLinkHasBeenCreatedYet": {},
|
||||
"chatCanBeDiscoveredViaSearchOnServer": "Chat kann über die Suche auf {server} gefunden werden",
|
||||
"@chatCanBeDiscoveredViaSearchOnServer": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"server": {}
|
||||
}
|
||||
},
|
||||
"appLockDescription": "App mit einer PIN sperren, wenn sie nicht verwendet wird",
|
||||
"@appLockDescription": {},
|
||||
"calls": "Anrufe",
|
||||
"@calls": {},
|
||||
"customEmojisAndStickers": "Eigene Emojis und Sticker",
|
||||
"@customEmojisAndStickers": {},
|
||||
"hideRedactedMessages": "Geschwärzte Nachrichten verstecken",
|
||||
"@hideRedactedMessages": {},
|
||||
"hideRedactedMessagesBody": "Wenn jemand eine Nachricht schwärzt/löscht, dann wird diese Nachricht im Chat nicht mehr sichtbar sein.",
|
||||
"@hideRedactedMessagesBody": {},
|
||||
"hideInvalidOrUnknownMessageFormats": "Ungültige und unbekannte Nachrichten-Formate ausblenden",
|
||||
"@hideInvalidOrUnknownMessageFormats": {},
|
||||
"overview": "Übersicht",
|
||||
"@overview": {},
|
||||
"notifyMeFor": "Benachrichtige mich für",
|
||||
"@notifyMeFor": {},
|
||||
"passwordRecoverySettings": "Passwort-Wiederherstellungs-Einstellungen",
|
||||
"@passwordRecoverySettings": {},
|
||||
"knock": "Anklopfen",
|
||||
"@knock": {},
|
||||
"knocking": "Klopft",
|
||||
"@knocking": {},
|
||||
"thereAreCountUsersBlocked": "Im Augenblick werden {count} Benutzer blockiert.",
|
||||
"@thereAreCountUsersBlocked": {
|
||||
"type": "text",
|
||||
"count": {}
|
||||
},
|
||||
"usersMustKnock": "Benutzer müssen anklopfen",
|
||||
"@usersMustKnock": {},
|
||||
"noOneCanJoin": "Niemand kann beitreten",
|
||||
"@noOneCanJoin": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@
|
|||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"appLockDescription": "Lock the app when not using with a pin code",
|
||||
"archive": "Archive",
|
||||
"@archive": {
|
||||
"type": "text",
|
||||
|
|
@ -773,6 +774,12 @@
|
|||
"type": "text",
|
||||
"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",
|
||||
"customEmojisAndStickers": "Custom emojis and stickers",
|
||||
"customEmojisAndStickersBody": "Add or share custom emojis or stickers which can be used in any chat.",
|
||||
"emoteShortcode": "Emote shortcode",
|
||||
"@emoteShortcode": {
|
||||
"type": "text",
|
||||
|
|
@ -958,7 +965,9 @@
|
|||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"hideUnknownEvents": "Hide unknown events",
|
||||
"hideRedactedMessages": "Hide redacted messages",
|
||||
"hideRedactedMessagesBody": "If someone redacts a message, this message won't be visible in the chat anymore.",
|
||||
"hideInvalidOrUnknownMessageFormats": "Hide invalid or unknown message formats",
|
||||
"@hideUnknownEvents": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
|
|
@ -1426,6 +1435,11 @@
|
|||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"hideMemberChangesInPublicChats": "Hide member changes in public chats",
|
||||
"hideMemberChangesInPublicChatsBody": "Do not show in the chat timeline if someone joins or leaves a public chat to improve readability.",
|
||||
"overview": "Overview",
|
||||
"notifyMeFor": "Notify me for",
|
||||
"passwordRecoverySettings": "Password recovery settings",
|
||||
"passwordRecovery": "Password recovery",
|
||||
"@passwordRecovery": {
|
||||
"type": "text",
|
||||
|
|
@ -2306,12 +2320,22 @@
|
|||
"user": {}
|
||||
}
|
||||
},
|
||||
"hasKnocked": "{user} has knocked",
|
||||
"hasKnocked": "🚪 {user} has knocked",
|
||||
"@hasKnocked": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"usersMustKnock": "Users must knock",
|
||||
"noOneCanJoin": "No one can join",
|
||||
"userWouldLikeToChangeTheChat": "{user} would like to join the chat.",
|
||||
"@userWouldLikeToChangeTheChat": {
|
||||
"placeholders": {
|
||||
"user": {}
|
||||
}
|
||||
},
|
||||
"noPublicLinkHasBeenCreatedYet": "No public link has been created yet",
|
||||
"knock": "Knock",
|
||||
"users": "Users",
|
||||
"@users": {},
|
||||
"unlockOldMessages": "Unlock old messages",
|
||||
|
|
@ -3725,6 +3749,14 @@
|
|||
"query": {}
|
||||
}
|
||||
},
|
||||
"knocking": "Knocking",
|
||||
"chatCanBeDiscoveredViaSearchOnServer": "Chat can be discovered via the search on {server}",
|
||||
"@chatCanBeDiscoveredViaSearchOnServer": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"server": {}
|
||||
}
|
||||
},
|
||||
"searchChatsRooms": "Search for #chats, @users...",
|
||||
"createClass": "Create class",
|
||||
"createExchange": "Create exchange",
|
||||
|
|
@ -3970,5 +4002,11 @@
|
|||
"capacitySetTooLow": "Room capacity cannot be set below the current number of non-admins.",
|
||||
"roomCapacityExplanation": "Room capacity limits the number of non-admins allowed in a room.",
|
||||
"enterNumber": "Please enter a whole number value.",
|
||||
"buildTranslation": "Build your translation from the choices above"
|
||||
"buildTranslation": "Build your translation from the choices above",
|
||||
"noDatabaseEncryption": "Database encryption is not supported on this platform",
|
||||
"thereAreCountUsersBlocked": "Right now there are {count} users blocked.",
|
||||
"@thereAreCountUsersBlocked": {
|
||||
"type": "text",
|
||||
"count": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -2616,5 +2616,7 @@
|
|||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"noDatabaseEncryption": "Plataforma honetan ezin da datu-basea zifratu",
|
||||
"@noDatabaseEncryption": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2616,5 +2616,7 @@
|
|||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"noDatabaseEncryption": "Nesta plataforma non temos soporte para cifrar a base de datos",
|
||||
"@noDatabaseEncryption": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2615,5 +2615,7 @@
|
|||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"noDatabaseEncryption": "Enkripsi basis data tidak didukung di platform ini",
|
||||
"@noDatabaseEncryption": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2484,5 +2484,136 @@
|
|||
"searchChatsRooms": "Buscar por #conversas, @usuários...",
|
||||
"@searchChatsRooms": {},
|
||||
"databaseMigrationBody": "Por favor, espere. Isto pode demorar um pouco.",
|
||||
"@databaseMigrationBody": {}
|
||||
"@databaseMigrationBody": {},
|
||||
"youInvitedToBy": "Você foi convidado através do link para:\n{alias}",
|
||||
"@youInvitedToBy": {
|
||||
"placeholders": {
|
||||
"alias": {}
|
||||
}
|
||||
},
|
||||
"forwardMessageTo": "Encaminhar mensagem para {roomName}?",
|
||||
"@forwardMessageTo": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"roomName": {}
|
||||
}
|
||||
},
|
||||
"formattedMessagesDescription": "Mostrar mensagens ricas com conteúdos tipo negrito usando markdown.",
|
||||
"@formattedMessagesDescription": {},
|
||||
"verifyOtherUser": "🔐 Verificar outro usuário",
|
||||
"@verifyOtherUser": {},
|
||||
"verifyOtherDevice": "🔐 Verificar outro aparelho",
|
||||
"@verifyOtherDevice": {},
|
||||
"acceptedKeyVerification": "{sender} aceitou sua chave de verificação",
|
||||
"@acceptedKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"startedKeyVerification": "{sender} iniciou a chave de verificação",
|
||||
"@startedKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"transparent": "Transparente",
|
||||
"@transparent": {},
|
||||
"databaseBuildErrorBody": "Não foi possível construir o banco de dados SQLite. O aplicativo tentará utilizar o banco de dados legado por enquanto. Por favor, reporte este erro aos desenvolvedores em {url}. A mensagem de erro é: {error}",
|
||||
"@databaseBuildErrorBody": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"url": {},
|
||||
"error": {}
|
||||
}
|
||||
},
|
||||
"initAppError": "Ocorreu um erro enquanto o aplicativo era iniciado",
|
||||
"@initAppError": {},
|
||||
"restoreSessionBody": "O aplicativo tentará agora restaurar sua sessão a partir do backup. Por favor, reporte este ao desenvolvedor em {url}. A mensagem de erro é: {error}",
|
||||
"@restoreSessionBody": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"url": {},
|
||||
"error": {}
|
||||
}
|
||||
},
|
||||
"sendReadReceipts": "Enviar recibos de leitura",
|
||||
"@sendReadReceipts": {},
|
||||
"sendTypingNotificationsDescription": "Outros participantes neste chat podem ver quando você está digitando uma nova mensagem.",
|
||||
"@sendTypingNotificationsDescription": {},
|
||||
"formattedMessages": "Mensagens formatadas",
|
||||
"@formattedMessages": {},
|
||||
"presenceStyle": "Presença:",
|
||||
"@presenceStyle": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"presencesToggle": "Mostrar o status das mensagens de outros usuários",
|
||||
"@presencesToggle": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"commandHint_ignore": "Ignorar o seguinte ID Matrix",
|
||||
"@commandHint_ignore": {},
|
||||
"commandHint_unignore": "Designorar o seguinte ID Matrix",
|
||||
"@commandHint_unignore": {},
|
||||
"hidePresences": "Esconder lista de status?",
|
||||
"@hidePresences": {},
|
||||
"sessionLostBody": "Sua sessão foi desconectada. Por favor, reporte este ao desenvolvedor em {url}. A mensagem de erro é: {error}",
|
||||
"@sessionLostBody": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"url": {},
|
||||
"error": {}
|
||||
}
|
||||
},
|
||||
"sendReadReceiptsDescription": "Outros participantes neste chat podem ver quando você tiver lido uma mensagem.",
|
||||
"@sendReadReceiptsDescription": {},
|
||||
"verifyOtherUserDescription": "Se você verificar outro usuário, você terá certeza que você conhece com quem está conversando. 💪\n\nQuando iniciar uma verificação, você e o outro usuário receberão um popup no aplicativo. Então vocês receberão uma série de emojis ou números para comparar um com o outro.\n\nA melhor maneira de fazer este procedimento é encontrar pessoalmente ou através de um vídeochamada. 👭",
|
||||
"@verifyOtherUserDescription": {},
|
||||
"requestedKeyVerification": "{sender} enviou uma chave de verificação",
|
||||
"@requestedKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"verifyOtherDeviceDescription": "Quando você verifica outro aparelho, estes aparelhos poderão trocar chaves, aumentando sua segurança. 💪\n\nQuando iniciar a verificação, um popup aparecerá no aplicativo em ambos os aparelhos. Então você verá uma série de emojis ou números que você terá que comparar um com o outro.\n\nÉ melhor fazer esse procedimento com ambos os aparelhos em mãos antes de começar a verificação. 🤳",
|
||||
"@verifyOtherDeviceDescription": {},
|
||||
"canceledKeyVerification": "{sender} cancelou sua chave de verificação",
|
||||
"@canceledKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"isReadyForKeyVerification": "{sender} está pronto para a chave de verificação",
|
||||
"@isReadyForKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"completedKeyVerification": "{sender} completou a chave de verificação",
|
||||
"@completedKeyVerification": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"sender": {}
|
||||
}
|
||||
},
|
||||
"stickers": "Stickers",
|
||||
"@stickers": {},
|
||||
"discover": "Descubra",
|
||||
"@discover": {},
|
||||
"incomingMessages": "Mensagens recebidas",
|
||||
"@incomingMessages": {},
|
||||
"unreadChatsInApp": "{appname}: {unread} mensagens não lidas",
|
||||
"@unreadChatsInApp": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"appname": {},
|
||||
"unread": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/archive/archive.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_list/chat_list.dart';
|
||||
import 'package:fluffychat/pages/chat_members/chat_members.dart';
|
||||
|
|
@ -546,6 +547,17 @@ abstract class AppRoutes {
|
|||
),
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'access',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
ChatAccessSettings(
|
||||
roomId: state.pathParameters['roomid']!,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'members',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ abstract class FluffyThemes {
|
|||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: colorScheme.secondaryContainer,
|
||||
foregroundColor: colorScheme.onSecondaryContainer,
|
||||
elevation: 0,
|
||||
padding: const EdgeInsets.all(16),
|
||||
textStyle: const TextStyle(fontSize: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
|
|
|
|||
|
|
@ -386,7 +386,10 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.red,
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.errorContainer,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onErrorContainer,
|
||||
),
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
label: Text(L10n.of(context)!.recoveryKeyLost),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
189
lib/pages/chat_access_settings/chat_access_settings_page.dart
Normal file
189
lib/pages/chat_access_settings/chat_access_settings_page.dart
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
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.localizedString(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(
|
||||
'https://matrix.to/#/${room.canonicalAlias}',
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension JoinRulesDisplayString on JoinRules {
|
||||
String localizedString(L10n l10n) {
|
||||
switch (this) {
|
||||
case JoinRules.public:
|
||||
return l10n.anyoneCanJoin;
|
||||
case JoinRules.invite:
|
||||
return l10n.invitedUsersOnly;
|
||||
case JoinRules.knock:
|
||||
return l10n.usersMustKnock;
|
||||
case JoinRules.private:
|
||||
return l10n.noOneCanJoin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,17 +7,14 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_des
|
|||
import 'package:fluffychat/pangea/utils/set_class_name.dart';
|
||||
import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart';
|
||||
import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/widgets/app_lock.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:matrix/matrix.dart' as matrix;
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
enum AliasActions { copy, delete, setCanonical }
|
||||
|
|
@ -83,122 +80,6 @@ class ChatDetailsController extends State<ChatDetails> {
|
|||
// }
|
||||
// Pangea#
|
||||
|
||||
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(
|
||||
// #Pangea
|
||||
useRootNavigator: false,
|
||||
// Pangea#
|
||||
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(
|
||||
// #Pangea
|
||||
useRootNavigator: false,
|
||||
// Pangea#
|
||||
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 {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||
// #Pangea
|
||||
|
|
@ -232,91 +113,6 @@ class ChatDetailsController extends State<ChatDetails> {
|
|||
// Pangea#
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ class ChatDetailsView extends StatelessWidget {
|
|||
}
|
||||
|
||||
return StreamBuilder(
|
||||
stream: room.onUpdate.stream,
|
||||
stream: room.client.onRoomState.stream
|
||||
.where((update) => update.roomId == room.id),
|
||||
builder: (context, snapshot) {
|
||||
var members = room.getParticipants().toList()
|
||||
..sort((b, a) => a.powerLevel.compareTo(b.powerLevel));
|
||||
|
|
@ -80,17 +81,16 @@ class ChatDetailsView extends StatelessWidget {
|
|||
elevation: Theme.of(context).appBarTheme.elevation,
|
||||
actions: <Widget>[
|
||||
// #Pangea
|
||||
//if (room.canonicalAlias.isNotEmpty)
|
||||
// IconButton(
|
||||
// tooltip: L10n.of(context)!.share,
|
||||
// icon: Icon(Icons.adaptive.share_outlined),
|
||||
// onPressed: () => FluffyShare.share(
|
||||
// L10n.of(context)!.youInvitedToBy(
|
||||
// AppConfig.inviteLinkPrefix + room.canonicalAlias,
|
||||
// ),
|
||||
// context,
|
||||
// ),
|
||||
// ),
|
||||
// if (room.canonicalAlias.isNotEmpty)
|
||||
// IconButton(
|
||||
// tooltip: L10n.of(context)!.share,
|
||||
// icon: Icon(Icons.adaptive.share_outlined),
|
||||
// onPressed: () => FluffyShare.share(
|
||||
// AppConfig.inviteLinkPrefix + room.canonicalAlias,
|
||||
// context,
|
||||
// ),
|
||||
// ),
|
||||
// Pangea#
|
||||
if (controller.widget.embeddedCloseButton == null)
|
||||
ChatSettingsPopupMenu(room, false),
|
||||
],
|
||||
|
|
@ -144,7 +144,6 @@ class ChatDetailsView extends StatelessWidget {
|
|||
mxContent: room.avatar,
|
||||
name: displayname,
|
||||
size: Avatar.defaultSize * 2.5,
|
||||
fontSize: 18 * 2.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -196,7 +195,7 @@ class ChatDetailsView extends StatelessWidget {
|
|||
style: TextButton.styleFrom(
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onBackground,
|
||||
.onSurface,
|
||||
),
|
||||
label: Text(
|
||||
room.isDirectChat
|
||||
|
|
@ -303,10 +302,18 @@ class ChatDetailsView extends StatelessWidget {
|
|||
// else
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(16.0),
|
||||
// child: OutlinedButton.icon(
|
||||
// child: TextButton.icon(
|
||||
// onPressed: controller.setTopicAction,
|
||||
// label: Text(L10n.of(context)!.setChatDescription),
|
||||
// icon: const Icon(Icons.edit_outlined),
|
||||
// style: TextButton.styleFrom(
|
||||
// backgroundColor: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .secondaryContainer,
|
||||
// foregroundColor: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .onSecondaryContainer,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
|
|
@ -341,23 +348,6 @@ class ChatDetailsView extends StatelessWidget {
|
|||
// height: 1,
|
||||
// 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(
|
||||
// leading: CircleAvatar(
|
||||
// backgroundColor:
|
||||
|
|
@ -367,7 +357,8 @@ class ChatDetailsView extends StatelessWidget {
|
|||
// Icons.insert_emoticon_outlined,
|
||||
// ),
|
||||
// ),
|
||||
// title: Text(L10n.of(context)!.emoteSettings),
|
||||
// title:
|
||||
// Text(L10n.of(context)!.customEmojisAndStickers),
|
||||
// subtitle: Text(L10n.of(context)!.setCustomEmotes),
|
||||
// onTap: controller.goToEmoteSettings,
|
||||
// trailing: const Icon(Icons.chevron_right_outlined),
|
||||
|
|
@ -381,71 +372,16 @@ class ChatDetailsView extends StatelessWidget {
|
|||
// child: const Icon(Icons.shield_outlined),
|
||||
// ),
|
||||
// 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,
|
||||
// L10n.of(context)!.accessAndVisibilityDescription,
|
||||
// ),
|
||||
// onTap: room.canChangeJoinRules
|
||||
// ? controller.setJoinRules
|
||||
// : null,
|
||||
// onTap: () => context
|
||||
// .push('/rooms/${room.id}/details/access'),
|
||||
// trailing: const Icon(Icons.chevron_right_outlined),
|
||||
// ),
|
||||
// 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(
|
||||
// room.historyVisibility?.getLocalizedString(
|
||||
// MatrixLocals(L10n.of(context)!),
|
||||
// ) ??
|
||||
// L10n.of(context)!.none,
|
||||
// ),
|
||||
// onTap: room.canChangeHistoryVisibility
|
||||
// ? controller.setHistoryVisibility
|
||||
// : null,
|
||||
// ),
|
||||
// if (room.jsoinRules == 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 &&
|
||||
!room.isSpace &&
|
||||
room.isRoomAdmin)
|
||||
|
|
@ -710,9 +646,12 @@ class ChatDetailsView extends StatelessWidget {
|
|||
// ListTile(
|
||||
// title: Text(L10n.of(context)!.inviteContact),
|
||||
// leading: CircleAvatar(
|
||||
// backgroundColor:
|
||||
// Theme.of(context).colorScheme.primary,
|
||||
// foregroundColor: Colors.white,
|
||||
// backgroundColor: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .primaryContainer,
|
||||
// foregroundColor: Theme.of(context)
|
||||
// .colorScheme
|
||||
// .onPrimaryContainer,
|
||||
// radius: Avatar.defaultSize / 2,
|
||||
// child: const Icon(Icons.add_outlined),
|
||||
// ),
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@ class ParticipantListItem extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final membershipBatch = <Membership, String>{
|
||||
Membership.join: '',
|
||||
Membership.ban: L10n.of(context)!.banned,
|
||||
Membership.invite: L10n.of(context)!.invited,
|
||||
Membership.leave: L10n.of(context)!.leftTheChat,
|
||||
final membershipBatch = switch (user.membership) {
|
||||
Membership.ban => L10n.of(context)!.banned,
|
||||
Membership.invite => L10n.of(context)!.invited,
|
||||
Membership.join => null,
|
||||
Membership.knock => L10n.of(context)!.knocking,
|
||||
Membership.leave => L10n.of(context)!.leftTheChat,
|
||||
};
|
||||
|
||||
final permissionBatch = user.powerLevel == 100
|
||||
? L10n.of(context)!.admin
|
||||
: user.powerLevel >= 50
|
||||
|
|
@ -70,7 +72,7 @@ class ParticipantListItem extends StatelessWidget {
|
|||
// Pangea#
|
||||
),
|
||||
),
|
||||
membershipBatch[user.membership]!.isEmpty
|
||||
membershipBatch == null
|
||||
? const SizedBox.shrink()
|
||||
: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
|
|
@ -79,8 +81,7 @@ class ParticipantListItem extends StatelessWidget {
|
|||
color: Theme.of(context).secondaryHeaderColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child:
|
||||
Center(child: Text(membershipBatch[user.membership]!)),
|
||||
child: Center(child: Text(membershipBatch)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'dart:developer';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
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:go_router/go_router.dart';
|
||||
|
|
@ -71,44 +70,6 @@ class ChatPermissionsSettingsController extends State<ChatPermissionsSettings> {
|
|||
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
|
||||
Widget build(BuildContext context) => ChatPermissionsSettingsView(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
|||
entry.value,
|
||||
),
|
||||
),
|
||||
const Divider(thickness: 1),
|
||||
Divider(color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.notifications,
|
||||
|
|
@ -87,7 +87,7 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
const Divider(thickness: 1),
|
||||
Divider(color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.configureChat,
|
||||
|
|
@ -109,33 +109,6 @@ class ChatPermissionsSettingsView extends StatelessWidget {
|
|||
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!),
|
||||
);
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -71,11 +71,6 @@ class DevicesSettingsView extends StatelessWidget {
|
|||
block: controller.blockDeviceAction,
|
||||
unblock: controller.unblockDeviceAction,
|
||||
),
|
||||
const Divider(
|
||||
height: 16.0,
|
||||
indent: 16,
|
||||
endIndent: 16,
|
||||
),
|
||||
],
|
||||
if (controller.notThisDevice.isNotEmpty)
|
||||
Padding(
|
||||
|
|
@ -85,17 +80,18 @@ class DevicesSettingsView extends StatelessWidget {
|
|||
),
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
child: TextButton.icon(
|
||||
label: Text(
|
||||
controller.errorDeletingDevices ??
|
||||
L10n.of(context)!.removeAllOtherDevices,
|
||||
),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.error,
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onErrorContainer,
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.errorContainer,
|
||||
),
|
||||
icon: controller.loadingDeletingDevices
|
||||
? const CircularProgressIndicator.adaptive(
|
||||
|
|
|
|||
|
|
@ -259,12 +259,7 @@ class _LoginButton extends StatelessWidget {
|
|||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: BorderSide(
|
||||
width: withBorder ? 1 : 0,
|
||||
color: withBorder
|
||||
? Theme.of(context).colorScheme.onBackground
|
||||
: Colors.transparent,
|
||||
),
|
||||
side: BorderSide.none,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class SettingsView extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
body: ListTileTheme(
|
||||
iconColor: Theme.of(context).colorScheme.onBackground,
|
||||
iconColor: Theme.of(context).colorScheme.onSurface,
|
||||
child: ListView(
|
||||
key: const Key('SettingsListViewContent'),
|
||||
children: <Widget>[
|
||||
|
|
@ -105,7 +105,7 @@ class SettingsView extends StatelessWidget {
|
|||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onBackground,
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
label: Text(
|
||||
displayname,
|
||||
|
|
@ -138,8 +138,11 @@ class SettingsView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
const Divider(thickness: 1),
|
||||
// #Pangea
|
||||
// Divider(
|
||||
// height: 1,
|
||||
// color: Theme.of(context).dividerColor,
|
||||
// ),
|
||||
// if (showChatBackupBanner == null)
|
||||
// ListTile(
|
||||
// leading: const Icon(Icons.backup_outlined),
|
||||
|
|
@ -154,7 +157,10 @@ class SettingsView extends StatelessWidget {
|
|||
// title: Text(L10n.of(context)!.chatBackup),
|
||||
// onChanged: controller.firstRunBootstrapAction,
|
||||
// ),
|
||||
// const Divider(thickness: 1),
|
||||
// Divider(
|
||||
// height: 1,
|
||||
// color: Theme.of(context).dividerColor,
|
||||
// ),
|
||||
// Pangea#
|
||||
ListTile(
|
||||
leading: const Icon(Icons.format_paint_outlined),
|
||||
|
|
@ -196,7 +202,10 @@ class SettingsView extends StatelessWidget {
|
|||
onTap: () => context.go('/rooms/settings/security'),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
),
|
||||
const Divider(thickness: 1),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.help_outline_outlined),
|
||||
title: Text(L10n.of(context)!.help),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/utils/voip/callkeep_manager.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:fluffychat/widgets/settings_switch_list_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -23,61 +21,85 @@ class SettingsChatView extends StatelessWidget {
|
|||
child: Column(
|
||||
children: [
|
||||
// #Pangea
|
||||
// ListTile(
|
||||
// title: Text(L10n.of(context)!.emoteSettings),
|
||||
// onTap: () => context.go('/rooms/settings/chat/emotes'),
|
||||
// trailing: const Icon(Icons.chevron_right_outlined),
|
||||
// leading: const Icon(Icons.emoji_emotions_outlined),
|
||||
// ),
|
||||
// const Divider(),
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.renderRichContent,
|
||||
// title: L10n.of(context)!.formattedMessages,
|
||||
// subtitle: L10n.of(context)!.formattedMessagesDescription,
|
||||
// onChanged: (b) => AppConfig.renderHtml = b,
|
||||
// storeKey: SettingKeys.renderHtml,
|
||||
// defaultValue: AppConfig.renderHtml,
|
||||
// ),
|
||||
// Pangea#
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.hideRedactedEvents,
|
||||
title: L10n.of(context)!.hideMemberChangesInPublicChats,
|
||||
subtitle: L10n.of(context)!.hideMemberChangesInPublicChatsBody,
|
||||
onChanged: (b) => AppConfig.hideUnimportantStateEvents = b,
|
||||
storeKey: SettingKeys.hideUnimportantStateEvents,
|
||||
defaultValue: AppConfig.hideUnimportantStateEvents,
|
||||
),
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.hideRedactedMessages,
|
||||
subtitle: L10n.of(context)!.hideRedactedMessagesBody,
|
||||
onChanged: (b) => AppConfig.hideRedactedEvents = b,
|
||||
storeKey: SettingKeys.hideRedactedEvents,
|
||||
defaultValue: AppConfig.hideRedactedEvents,
|
||||
),
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.hideUnknownEvents,
|
||||
title: L10n.of(context)!.hideInvalidOrUnknownMessageFormats,
|
||||
onChanged: (b) => AppConfig.hideUnknownEvents = b,
|
||||
storeKey: SettingKeys.hideUnknownEvents,
|
||||
defaultValue: AppConfig.hideUnknownEvents,
|
||||
),
|
||||
// #Pangea
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.hideUnimportantStateEvents,
|
||||
// onChanged: (b) => AppConfig.hideUnimportantStateEvents = b,
|
||||
// storeKey: SettingKeys.hideUnimportantStateEvents,
|
||||
// defaultValue: AppConfig.hideUnimportantStateEvents,
|
||||
// ),
|
||||
// Pangea#
|
||||
if (PlatformInfos.isMobile)
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.autoplayImages,
|
||||
onChanged: (b) => AppConfig.autoplayImages = b,
|
||||
storeKey: SettingKeys.autoplayImages,
|
||||
defaultValue: AppConfig.autoplayImages,
|
||||
),
|
||||
const Divider(),
|
||||
// if (PlatformInfos.isMobile)
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.autoplayImages,
|
||||
// onChanged: (b) => AppConfig.autoplayImages = b,
|
||||
// storeKey: SettingKeys.autoplayImages,
|
||||
// defaultValue: AppConfig.autoplayImages,
|
||||
// ),
|
||||
// Pangea#
|
||||
// #Pangea
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.sendTypingNotifications,
|
||||
// onChanged: (b) => AppConfig.sendTypingNotifications = b,
|
||||
// storeKey: SettingKeys.sendTypingNotifications,
|
||||
// defaultValue: AppConfig.sendTypingNotifications,
|
||||
// ),
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.sendOnEnter,
|
||||
// onChanged: (b) => AppConfig.sendOnEnter = b,
|
||||
// storeKey: SettingKeys.sendOnEnter,
|
||||
// defaultValue: AppConfig.sendOnEnter ?? !PlatformInfos.isMobile,
|
||||
// ),
|
||||
// Divider(
|
||||
// height: 1,
|
||||
// color: Theme.of(context).dividerColor,
|
||||
// ),
|
||||
// ListTile(
|
||||
// title: Text(
|
||||
// L10n.of(context)!.customEmojisAndStickers,
|
||||
// style: TextStyle(
|
||||
// color: Theme.of(context).colorScheme.secondary,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ListTile(
|
||||
// title: Text(L10n.of(context)!.customEmojisAndStickers),
|
||||
// subtitle: Text(L10n.of(context)!.customEmojisAndStickersBody),
|
||||
// onTap: () => context.go('/rooms/settings/chat/emotes'),
|
||||
// trailing: const Padding(
|
||||
// padding: EdgeInsets.all(16.0),
|
||||
// child: Icon(Icons.chevron_right_outlined),
|
||||
// ),
|
||||
// ),
|
||||
// Divider(
|
||||
// height: 1,
|
||||
// color: Theme.of(context).dividerColor,
|
||||
// ),
|
||||
// ListTile(
|
||||
// title: Text(
|
||||
// L10n.of(context)!.calls,
|
||||
// style: TextStyle(
|
||||
// color: Theme.of(context).colorScheme.secondary,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context)!.experimentalVideoCalls,
|
||||
// onChanged: (b) {
|
||||
|
|
@ -88,23 +110,17 @@ class SettingsChatView extends StatelessWidget {
|
|||
// storeKey: SettingKeys.experimentalVoip,
|
||||
// defaultValue: AppConfig.experimentalVoip,
|
||||
// ),
|
||||
// if (PlatformInfos.isMobile)
|
||||
// ListTile(
|
||||
// title: Text(L10n.of(context)!.callingPermissions),
|
||||
// onTap: () =>
|
||||
// CallKeepManager().checkoutPhoneAccountSetting(context),
|
||||
// trailing: const Padding(
|
||||
// padding: EdgeInsets.all(16.0),
|
||||
// child: Icon(Icons.call),
|
||||
// ),
|
||||
// ),
|
||||
// Pangea#
|
||||
if (PlatformInfos.isMobile)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.callingPermissions),
|
||||
onTap: () =>
|
||||
CallKeepManager().checkoutPhoneAccountSetting(context),
|
||||
trailing: const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Icon(Icons.call),
|
||||
),
|
||||
),
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.separateChatTypes,
|
||||
onChanged: (b) => AppConfig.separateChatTypes = b,
|
||||
storeKey: SettingKeys.separateChatTypes,
|
||||
defaultValue: AppConfig.separateChatTypes,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class EmotesSettingsView extends StatelessWidget {
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const Center(child: BackButton()),
|
||||
title: Text(L10n.of(context)!.emoteSettings),
|
||||
title: Text(L10n.of(context)!.customEmojisAndStickers),
|
||||
actions: [
|
||||
PopupMenuButton<PopupMenuEmojiActions>(
|
||||
onSelected: (value) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../../widgets/matrix.dart';
|
||||
import 'settings_ignore_list_view.dart';
|
||||
|
|
@ -25,9 +27,20 @@ class SettingsIgnoreListController extends State<SettingsIgnoreList> {
|
|||
}
|
||||
}
|
||||
|
||||
String? errorText;
|
||||
|
||||
void ignoreUser(BuildContext context) {
|
||||
if (controller.text.isEmpty) return;
|
||||
final userId = '@${controller.text}';
|
||||
final userId = controller.text.trim();
|
||||
if (userId.isEmpty) return;
|
||||
if (!userId.isValidMatrixId || userId.sigil != '@') {
|
||||
setState(() {
|
||||
errorText = L10n.of(context)!.invalidInput;
|
||||
});
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
errorText = null;
|
||||
});
|
||||
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@ class SettingsIgnoreListView extends StatelessWidget {
|
|||
textInputAction: TextInputAction.done,
|
||||
onSubmitted: (_) => controller.ignoreUser(context),
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'bad_guy:domain.abc',
|
||||
prefixText: '@',
|
||||
errorText: controller.errorText,
|
||||
hintText: '@bad_guy:domain.abc',
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
labelText: L10n.of(context)!.blockUsername,
|
||||
suffixIcon: IconButton(
|
||||
tooltip: L10n.of(context)!.block,
|
||||
icon: const Icon(Icons.done_outlined),
|
||||
icon: const Icon(Icons.send_outlined),
|
||||
onPressed: () => controller.ignoreUser(context),
|
||||
),
|
||||
),
|
||||
|
|
@ -56,7 +56,9 @@ class SettingsIgnoreListView extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
Expanded(
|
||||
child: StreamBuilder<Object>(
|
||||
stream: client.onAccountData.stream
|
||||
|
|
@ -75,9 +77,11 @@ class SettingsIgnoreListView extends StatelessWidget {
|
|||
title: Text(
|
||||
s.data?.displayName ?? client.ignoredUsers[i],
|
||||
),
|
||||
subtitle:
|
||||
Text(s.data?.userId ?? client.ignoredUsers[i]),
|
||||
trailing: IconButton(
|
||||
tooltip: L10n.of(context)!.delete,
|
||||
icon: const Icon(Icons.delete_forever_outlined),
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
onPressed: () => showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () =>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ 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/utils/localized_exception_extension.dart';
|
||||
import '../../widgets/matrix.dart';
|
||||
import 'settings_notifications_view.dart';
|
||||
|
||||
|
|
@ -89,16 +90,52 @@ class SettingsNotificationsController extends State<SettingsNotifications> {
|
|||
}
|
||||
}
|
||||
|
||||
void setNotificationSetting(NotificationSettingsItem item, bool enabled) {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => Matrix.of(context).client.setPushRuleEnabled(
|
||||
bool isLoading = false;
|
||||
|
||||
void setNotificationSetting(
|
||||
NotificationSettingsItem item,
|
||||
bool enabled,
|
||||
) async {
|
||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
try {
|
||||
await Matrix.of(context).client.setPushRuleEnabled(
|
||||
'global',
|
||||
item.type,
|
||||
item.key,
|
||||
enabled,
|
||||
),
|
||||
);
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to change notification settings', e, s);
|
||||
scaffoldMessenger
|
||||
.showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void onToggleMuteAllNotifications() async {
|
||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
try {
|
||||
await Matrix.of(context).client.setMuteAllPushNotifications(
|
||||
!Matrix.of(context).client.allPushNotificationsMuted,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to change notification settings', e, s);
|
||||
scaffoldMessenger
|
||||
.showSnackBar(SnackBar(content: Text(e.toLocalizedString(context))));
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void onPusherTap(Pusher pusher) async {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.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/widgets/layouts/max_width_body.dart';
|
||||
|
|
@ -36,13 +35,18 @@ class SettingsNotificationsView extends StatelessWidget {
|
|||
title: Text(
|
||||
L10n.of(context)!.notificationsEnabledForThisAccount,
|
||||
),
|
||||
onChanged: (_) => showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => Matrix.of(context)
|
||||
.client
|
||||
.setMuteAllPushNotifications(
|
||||
!Matrix.of(context).client.allPushNotificationsMuted,
|
||||
),
|
||||
onChanged: controller.isLoading
|
||||
? null
|
||||
: (_) => controller.onToggleMuteAllNotifications(),
|
||||
),
|
||||
Divider(color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.notifyMeFor,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
for (final item in NotificationSettingsItem.items)
|
||||
|
|
@ -51,14 +55,14 @@ class SettingsNotificationsView extends StatelessWidget {
|
|||
? false
|
||||
: controller.getNotificationSetting(item) ?? true,
|
||||
title: Text(item.title(context)),
|
||||
onChanged: Matrix.of(context)
|
||||
.client
|
||||
.allPushNotificationsMuted
|
||||
onChanged: controller.isLoading
|
||||
? null
|
||||
: (bool enabled) =>
|
||||
controller.setNotificationSetting(item, enabled),
|
||||
: Matrix.of(context).client.allPushNotificationsMuted
|
||||
? null
|
||||
: (bool enabled) => controller
|
||||
.setNotificationSetting(item, enabled),
|
||||
),
|
||||
const Divider(),
|
||||
Divider(color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.devices,
|
||||
|
|
@ -87,6 +91,14 @@ class SettingsNotificationsView extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
final pushers = snapshot.data ?? [];
|
||||
if (pushers.isEmpty) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16.0),
|
||||
child: Text(L10n.of(context)!.noOtherDevicesFound),
|
||||
),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:fluffychat/pages/settings_password/settings_password.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
|
|
@ -12,7 +13,15 @@ class SettingsPasswordView extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(L10n.of(context)!.changePassword)),
|
||||
appBar: AppBar(
|
||||
title: Text(L10n.of(context)!.changePassword),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(L10n.of(context)!.passwordRecoverySettings),
|
||||
onPressed: () => context.go('/rooms/settings/security/3pid'),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListTileTheme(
|
||||
iconColor: Theme.of(context).colorScheme.onBackground,
|
||||
child: MaxWidthBody(
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
|
|||
message: L10n.of(context)!.deactivateAccountWarning,
|
||||
okLabel: L10n.of(context)!.ok,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
isDestructiveAction: true,
|
||||
) ==
|
||||
OkCancelResult.cancel) {
|
||||
return;
|
||||
|
|
@ -74,6 +75,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
|
|||
: L10n.of(context)!.supposedMxid(supposedMxid),
|
||||
),
|
||||
],
|
||||
isDestructiveAction: true,
|
||||
okLabel: L10n.of(context)!.delete,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
);
|
||||
|
|
@ -86,6 +88,7 @@ class SettingsSecurityController extends State<SettingsSecurity> {
|
|||
title: L10n.of(context)!.pleaseEnterYourPassword,
|
||||
okLabel: L10n.of(context)!.ok,
|
||||
cancelLabel: L10n.of(context)!.cancel,
|
||||
isDestructiveAction: true,
|
||||
textFields: [
|
||||
const DialogTextField(
|
||||
obscureText: true,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/utils/beautify_string_extension.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
|
@ -41,95 +40,15 @@ class SettingsSecurityView extends StatelessWidget {
|
|||
}
|
||||
return Column(
|
||||
children: [
|
||||
if (error != null)
|
||||
ListTile(
|
||||
leading: const Icon(
|
||||
Icons.warning_outlined,
|
||||
color: Colors.orange,
|
||||
),
|
||||
title: Text(
|
||||
error.toLocalizedString(context),
|
||||
style: const TextStyle(color: Colors.orange),
|
||||
),
|
||||
),
|
||||
if (capabilities?.mChangePassword?.enabled != false ||
|
||||
error != null) ...[
|
||||
ListTile(
|
||||
leading: const Icon(Icons.key_outlined),
|
||||
trailing: error != null
|
||||
? null
|
||||
: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(
|
||||
L10n.of(context)!.changePassword,
|
||||
style: TextStyle(
|
||||
decoration:
|
||||
error == null ? null : TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
onTap: error != null
|
||||
? null
|
||||
: () =>
|
||||
context.go('/rooms/settings/security/password'),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.mail_outlined),
|
||||
trailing: error != null
|
||||
? null
|
||||
: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(
|
||||
L10n.of(context)!.passwordRecovery,
|
||||
style: TextStyle(
|
||||
decoration:
|
||||
error == null ? null : TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
onTap: error != null
|
||||
? null
|
||||
: () => context.go('/rooms/settings/security/3pid'),
|
||||
),
|
||||
],
|
||||
ListTile(
|
||||
leading: const Icon(Icons.block_outlined),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(L10n.of(context)!.blockedUsers),
|
||||
onTap: () =>
|
||||
context.go('/rooms/settings/security/ignorelist'),
|
||||
),
|
||||
if (Matrix.of(context).client.encryption != null) ...{
|
||||
if (PlatformInfos.isMobile)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.lock_outlined),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(L10n.of(context)!.appLock),
|
||||
onTap: controller.setAppLockAction,
|
||||
),
|
||||
},
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.tap_and_play),
|
||||
title: Text(
|
||||
L10n.of(context)!.dehydrate,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
L10n.of(context)!.privacy,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
onTap: controller.dehydrateAction,
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.delete_outlined),
|
||||
title: Text(
|
||||
L10n.of(context)!.deleteAccount,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
onTap: controller.deleteAccountAction,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.yourPublicKey),
|
||||
subtitle: SelectableText(
|
||||
Matrix.of(context).client.fingerprintKey.beautified,
|
||||
style: const TextStyle(fontFamily: 'monospace'),
|
||||
),
|
||||
leading: const Icon(Icons.vpn_key_outlined),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.sendTypingNotifications,
|
||||
subtitle:
|
||||
|
|
@ -145,6 +64,74 @@ class SettingsSecurityView extends StatelessWidget {
|
|||
storeKey: SettingKeys.sendPublicReadReceipts,
|
||||
defaultValue: AppConfig.sendPublicReadReceipts,
|
||||
),
|
||||
ListTile(
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(L10n.of(context)!.blockedUsers),
|
||||
subtitle: Text(
|
||||
L10n.of(context)!.thereAreCountUsersBlocked(
|
||||
Matrix.of(context).client.ignoredUsers.length,
|
||||
),
|
||||
),
|
||||
onTap: () =>
|
||||
context.go('/rooms/settings/security/ignorelist'),
|
||||
),
|
||||
if (Matrix.of(context).client.encryption != null) ...{
|
||||
if (PlatformInfos.isMobile)
|
||||
ListTile(
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(L10n.of(context)!.appLock),
|
||||
subtitle: Text(L10n.of(context)!.appLockDescription),
|
||||
onTap: controller.setAppLockAction,
|
||||
),
|
||||
},
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.account,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.yourPublicKey),
|
||||
leading: const Icon(Icons.vpn_key_outlined),
|
||||
subtitle: SelectableText(
|
||||
Matrix.of(context).client.fingerprintKey.beautified,
|
||||
style: const TextStyle(fontFamily: 'monospace'),
|
||||
),
|
||||
),
|
||||
if (capabilities?.mChangePassword?.enabled != false ||
|
||||
error != null)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.password_outlined),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
title: Text(L10n.of(context)!.changePassword),
|
||||
onTap: () =>
|
||||
context.go('/rooms/settings/security/password'),
|
||||
),
|
||||
ListTile(
|
||||
iconColor: Colors.orange,
|
||||
leading: const Icon(Icons.tap_and_play),
|
||||
title: Text(
|
||||
L10n.of(context)!.dehydrate,
|
||||
style: const TextStyle(color: Colors.orange),
|
||||
),
|
||||
onTap: controller.dehydrateAction,
|
||||
),
|
||||
ListTile(
|
||||
iconColor: Colors.red,
|
||||
leading: const Icon(Icons.delete_outlined),
|
||||
title: Text(
|
||||
L10n.of(context)!.deleteAccount,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
onTap: controller.deleteAccountAction,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -135,7 +135,10 @@ class SettingsStyleView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Divider(height: 1),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.setTheme,
|
||||
|
|
@ -163,10 +166,13 @@ class SettingsStyleView extends StatelessWidget {
|
|||
title: Text(L10n.of(context)!.darkTheme),
|
||||
onChanged: controller.switchTheme,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.presenceStyle,
|
||||
L10n.of(context)!.overview,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
|
@ -179,7 +185,16 @@ class SettingsStyleView extends StatelessWidget {
|
|||
storeKey: SettingKeys.showPresences,
|
||||
defaultValue: AppConfig.showPresences,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
SettingsSwitchListTile.adaptive(
|
||||
title: L10n.of(context)!.separateChatTypes,
|
||||
onChanged: (b) => AppConfig.separateChatTypes = b,
|
||||
storeKey: SettingKeys.separateChatTypes,
|
||||
defaultValue: AppConfig.separateChatTypes,
|
||||
),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.messagesStyle,
|
||||
|
|
|
|||
|
|
@ -260,6 +260,26 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
|||
}
|
||||
}
|
||||
|
||||
void knockAccept() async {
|
||||
final user = widget.user!;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.room.invite(user.id),
|
||||
);
|
||||
if (result.error != null) return;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void knockDecline() async {
|
||||
final user = widget.user!;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.room.kick(user.id),
|
||||
);
|
||||
if (result.error != null) return;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => UserBottomSheetView(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|||
import 'package:flutter_linkify/flutter_linkify.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/fluffy_share.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
|
|
@ -105,6 +106,51 @@ class UserBottomSheetView extends StatelessWidget {
|
|||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
if (user?.membership == Membership.knock)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
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: controller.knockAccept,
|
||||
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: controller.knockDecline,
|
||||
icon: const Icon(Icons.cancel_outlined),
|
||||
label: Text(L10n.of(context)!.decline),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ extension IsStateExtension on Event {
|
|||
(isState || !AppConfig.hideAllStateEvents) &&
|
||||
// #Pangea
|
||||
content.tryGet(ModelKey.transcription) == null &&
|
||||
// Pangea#
|
||||
// hide unimportant state events
|
||||
(!AppConfig.hideUnimportantStateEvents ||
|
||||
!isState ||
|
||||
importantStateEvents.contains(type)) &&
|
||||
// Pangea#
|
||||
// hide simple join/leave member events in public rooms
|
||||
(!AppConfig.hideUnimportantStateEvents ||
|
||||
type != EventTypes.RoomMember ||
|
||||
|
|
@ -33,6 +33,13 @@ extension IsStateExtension on Event {
|
|||
content.tryGet<String>('membership') == 'ban' ||
|
||||
stateKey != senderId);
|
||||
|
||||
bool get isState => !{
|
||||
EventTypes.Message,
|
||||
EventTypes.Sticker,
|
||||
EventTypes.Encrypted,
|
||||
}.contains(type);
|
||||
|
||||
// #Pangea
|
||||
static const Set<String> importantStateEvents = {
|
||||
EventTypes.Encryption,
|
||||
EventTypes.RoomCreate,
|
||||
|
|
@ -40,10 +47,5 @@ extension IsStateExtension on Event {
|
|||
EventTypes.RoomTombstone,
|
||||
EventTypes.CallInvite,
|
||||
};
|
||||
|
||||
bool get isState => !{
|
||||
EventTypes.Message,
|
||||
EventTypes.Sticker,
|
||||
EventTypes.Encrypted,
|
||||
}.contains(type);
|
||||
// Pangea#
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,17 +31,18 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
|||
void _joinRoom(BuildContext context) async {
|
||||
final client = Matrix.of(outerContext).client;
|
||||
final chunk = this.chunk;
|
||||
final knock = chunk?.joinRule == 'knock';
|
||||
final result = await showFutureLoadingDialog<String>(
|
||||
context: context,
|
||||
future: () async {
|
||||
if (chunk != null && client.getRoomById(chunk.roomId) != null) {
|
||||
return chunk.roomId;
|
||||
}
|
||||
final roomId = chunk != null && chunk.joinRule == 'knock'
|
||||
final roomId = chunk != null && knock
|
||||
? await client.knockRoom(chunk.roomId)
|
||||
: await client.joinRoom(roomAlias ?? chunk!.roomId);
|
||||
|
||||
if (client.getRoomById(roomId) == null) {
|
||||
if (!knock && client.getRoomById(roomId) == null) {
|
||||
await client.waitForRoomInSync(roomId);
|
||||
}
|
||||
// #Pangea
|
||||
|
|
@ -53,6 +54,9 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
|||
return roomId;
|
||||
},
|
||||
);
|
||||
if (knock) {
|
||||
return;
|
||||
}
|
||||
if (result.error == null) {
|
||||
Navigator.of(context).pop();
|
||||
// don't open the room if the joined room is a space
|
||||
|
|
@ -144,9 +148,15 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
|||
child: ElevatedButton.icon(
|
||||
onPressed: () => _joinRoom(context),
|
||||
label: Text(
|
||||
chunk?.roomType == 'm.space'
|
||||
? L10n.of(context)!.joinSpace
|
||||
: L10n.of(context)!.joinRoom,
|
||||
chunk?.joinRule == 'knock' &&
|
||||
Matrix.of(context)
|
||||
.client
|
||||
.getRoomById(chunk!.roomId) ==
|
||||
null
|
||||
? L10n.of(context)!.knock
|
||||
: chunk?.roomType == 'm.space'
|
||||
? L10n.of(context)!.joinSpace
|
||||
: L10n.of(context)!.joinRoom,
|
||||
),
|
||||
icon: const Icon(Icons.login_outlined),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue