diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 0316172e9..793c97447 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3943,6 +3943,10 @@ "groupName": "Group name", "createGroupAndInviteUsers": "Create a group and invite users", "groupCanBeFoundViaSearch": "Group can be found via search", + "inNoSpaces": "You are not a member of any classes or exchanges", + "createClass": "Create class", + "createExchange": "Create exchange", + "viewArchive": "View Archive", "trialExpiration": "Your free trial expires on {expiration}", "@trialExpiration": { "placeholders": { diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 4f83f18e6..fa9bce826 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -76,7 +76,8 @@ class ChatEventList extends StatelessWidget { // #Pangea if (i == 1) { - return controller.room.locked && !controller.room.isRoomAdmin + return (controller.room.locked ?? false) && + !controller.room.isRoomAdmin ? const LockedChatMessage() : const SizedBox.shrink(); } diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index d3499a0bf..ee14bda2d 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -547,18 +547,23 @@ class ChatDetailsView extends StatelessWidget { Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, child: Icon( - room.locked + room.locked ?? false ? Icons.lock_outlined : Icons.no_encryption_outlined, ), ), - value: room.locked, + value: room.locked ?? false, onChanged: (value) => showFutureLoadingDialog( context: context, - future: () => toggleLockRoom( - room, - Matrix.of(context).client, - ), + future: () => value + ? lockRoom( + room, + Matrix.of(context).client, + ) + : unlockRoom( + room, + Matrix.of(context).client, + ), ), ), const Divider(height: 1), diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index d535b2e65..81712de78 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -1,16 +1,15 @@ -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'; -import 'package:matrix/matrix.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/utils/get_chat_list_item_subtitle.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/room_status_extension.dart'; +import 'package:flutter/material.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:matrix/matrix.dart'; + import '../../config/themes.dart'; import '../../utils/date_time_extension.dart'; import '../../widgets/avatar.dart'; @@ -341,6 +340,16 @@ class ChatListItem extends StatelessWidget { ), ), const SizedBox(width: 8), + // #Pangea + if (room.locked ?? false) + const Padding( + padding: EdgeInsets.only(right: 4.0), + child: Icon( + Icons.lock_outlined, + size: 16, + ), + ), + // Pangea# AnimatedContainer( duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 5907d9f08..e4a777c80 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -1,19 +1,19 @@ import 'dart:developer'; +import 'package:fluffychat/pangea/extensions/client_extension.dart'; +import 'package:fluffychat/pangea/utils/class_code.dart'; +import 'package:fluffychat/pangea/utils/find_conversation_partner_dialog.dart'; +import 'package:fluffychat/pangea/utils/logout.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +// Project imports: import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; import 'package:keyboard_shortcuts/keyboard_shortcuts.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/extensions/client_extension.dart'; -import 'package:fluffychat/pangea/utils/class_code.dart'; -import 'package:fluffychat/pangea/utils/find_conversation_partner_dialog.dart'; -import 'package:fluffychat/pangea/utils/logout.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import '../../utils/fluffy_share.dart'; import 'chat_list.dart'; @@ -159,7 +159,7 @@ class ClientChooserButton extends StatelessWidget { const SizedBox(width: 18), // #Pangea // Text(L10n.of(context)!.archive), - Expanded(child: Text(L10n.of(context)!.archive)), + Expanded(child: Text(L10n.of(context)!.viewArchive)), // Pangea# ], ), diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index f88596085..7d48fa52f 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -1,14 +1,7 @@ import 'dart:async'; -import 'package:flutter/material.dart'; - import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.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:matrix/matrix.dart'; - import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; @@ -18,6 +11,12 @@ import 'package:fluffychat/pangea/utils/archive_space.dart'; import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/widgets/avatar.dart'; +import 'package:flutter/material.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:matrix/matrix.dart'; + import '../../utils/localized_exception_extension.dart'; import '../../widgets/matrix.dart'; import 'chat_list_header.dart'; @@ -267,12 +266,24 @@ class _SpaceViewState extends State { overflow: TextOverflow.ellipsis, ), // #Pangea - subtitle: Text( - rootSpace.membership == Membership.join - ? L10n.of(context)!.numChats( - rootSpace.spaceChildren.length.toString(), - ) - : L10n.of(context)!.youreInvited, + subtitle: Row( + children: [ + Text( + rootSpace.membership == Membership.join + ? L10n.of(context)!.numChats( + rootSpace.spaceChildren.length.toString(), + ) + : L10n.of(context)!.youreInvited, + ), + if (rootSpace.locked ?? false) + const Padding( + padding: EdgeInsets.only(left: 4.0), + child: Icon( + Icons.lock_outlined, + size: 16, + ), + ), + ], ), onTap: () => chatListHandleSpaceTap( context, diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 32027cb84..11cb9a542 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -1,15 +1,16 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart'; +import 'package:fluffychat/pangea/extensions/client_extension.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart'; import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; import 'package:fluffychat/pangea/widgets/space/class_settings.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.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 'new_space.dart'; class NewSpaceView extends StatelessWidget { @@ -81,6 +82,8 @@ class NewSpaceView extends StatelessWidget { key: controller.classSettingsKey, roomId: null, startOpen: true, + initialSettings: + Matrix.of(context).client.lastUpdatedClassSettings, ), if (!controller.newClassMode) AddToSpaceToggles( @@ -94,8 +97,8 @@ class NewSpaceView extends StatelessWidget { key: controller.rulesEditorKey, roomId: null, startOpen: false, + initialRules: Matrix.of(context).client.lastUpdatedRoomRules, ), - const SizedBox(height: 45), // SwitchListTile.adaptive( // title: Text(L10n.of(context)!.spaceIsPublic), // value: controller.publicGroup, @@ -108,14 +111,41 @@ class NewSpaceView extends StatelessWidget { // ), // subtitle: Text(L10n.of(context)!.newSpaceDescription), // ), + Padding( + padding: const EdgeInsets.all(16.0), + child: SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Theme.of(context).colorScheme.onPrimary, + backgroundColor: Theme.of(context).colorScheme.primary, + ), + onPressed: controller.submitAction, + child: Row( + children: [ + Expanded( + child: Text( + controller.newClassMode + ? L10n.of(context)!.createClass + : L10n.of(context)!.createExchange, + ), + ), + Icon(Icons.adaptive.arrow_forward_outlined), + ], + ), + ), + ), + ), // Pangea# ], ), ), - floatingActionButton: FloatingActionButton( - onPressed: controller.submitAction, - child: const Icon(Icons.arrow_forward_outlined), - ), + // #Pangea + // floatingActionButton: FloatingActionButton( + // onPressed: controller.submitAction, + // child: const Icon(Icons.arrow_forward_outlined), + // ), + // Pangea# ); } } diff --git a/lib/pangea/extensions/client_extension.dart b/lib/pangea/extensions/client_extension.dart index d226c78a7..090530f1a 100644 --- a/lib/pangea/extensions/client_extension.dart +++ b/lib/pangea/extensions/client_extension.dart @@ -1,16 +1,16 @@ import 'dart:developer'; -import 'package:flutter/foundation.dart'; - import 'package:collection/collection.dart'; -import 'package:matrix/matrix.dart'; - import 'package:fluffychat/pangea/constants/class_default_values.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:flutter/foundation.dart'; +import 'package:matrix/matrix.dart'; + import '../utils/p_store.dart'; extension PangeaClient on Client { @@ -152,4 +152,21 @@ extension PangeaClient on Client { ); return getRoomById(roomId)!; } + + PangeaRoomRules? get lastUpdatedRoomRules => classesAndExchangesImTeaching + .where((space) => space.rulesUpdatedAt != null) + .sorted( + (a, b) => b.rulesUpdatedAt!.compareTo(a.rulesUpdatedAt!), + ) + .firstOrNull + ?.pangeaRoomRules; + + ClassSettingsModel? get lastUpdatedClassSettings => classesImTeaching + .where((space) => space.classSettingsUpdatedAt != null) + .sorted( + (a, b) => + b.classSettingsUpdatedAt!.compareTo(a.classSettingsUpdatedAt!), + ) + .firstOrNull + ?.classSettings; } diff --git a/lib/pangea/extensions/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension.dart index b0d2d1bc2..624437666 100644 --- a/lib/pangea/extensions/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension.dart @@ -77,6 +77,8 @@ extension PangeaRoom on Room { String? get creatorId => getState(EventTypes.RoomCreate)?.senderId; + DateTime? get creationTime => getState(EventTypes.RoomCreate)?.originServerTs; + ClassSettingsModel? get firstLanguageSettings => classSettings ?? firstParentWithState(PangeaEventTypes.classSettings)?.classSettings; @@ -906,29 +908,20 @@ extension PangeaRoom on Room { ); } - bool get locked { - final Event? powerLevels = getState(EventTypes.RoomPowerLevels); - if (powerLevels == null) { - return false; - } - final Map powerLevelsContent = Map.from( - powerLevels.content, - ); + int? get eventsDefaultPowerLevel => getState(EventTypes.RoomPowerLevels) + ?.content + .tryGet('events_default'); + bool? get locked { + if (isDirectChat) return false; if (!isSpace) { - return powerLevelsContent['events_default'] != null && - powerLevelsContent['events_default'] >= 100; + if (eventsDefaultPowerLevel == null) return null; + return eventsDefaultPowerLevel! >= ClassDefaultValues.powerLevelOfAdmin; } - - final List children = spaceChildren - .map( - (child) => - child.roomId != null ? client.getRoomById(child.roomId!) : null, - ) - .toList(); - - for (final Room? child in children) { - if (child != null && !child.locked) { + for (final child in spaceChildren) { + if (child.roomId == null) continue; + final Room? room = client.getRoomById(child.roomId!); + if (room?.locked == false && (room?.canChangePowerLevel ?? false)) { return false; } } @@ -972,4 +965,14 @@ extension PangeaRoom on Room { } return children; } + + DateTime? get classSettingsUpdatedAt { + if (!isSpace) return null; + return languageSettingsStateEvent?.originServerTs ?? creationTime; + } + + DateTime? get rulesUpdatedAt { + if (!isSpace) return null; + return pangeaRoomRulesStateEvent?.originServerTs ?? creationTime; + } } diff --git a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart index c9e157e12..9c7823e5b 100644 --- a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart +++ b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart @@ -1,10 +1,9 @@ +import 'package:fluffychat/pangea/models/class_model.dart'; 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/pangea/models/class_model.dart'; import '../../../../config/app_config.dart'; import '../../../../widgets/matrix.dart'; import '../../../constants/pangea_event_types.dart'; @@ -14,12 +13,14 @@ class RoomRulesEditor extends StatefulWidget { final String? roomId; final bool startOpen; final bool showAdd; + final PangeaRoomRules? initialRules; const RoomRulesEditor({ super.key, this.roomId, this.startOpen = true, this.showAdd = false, + this.initialRules, }); @override @@ -43,7 +44,7 @@ class RoomRulesState extends State { ? Matrix.of(context).client.getRoomById(widget.roomId!) : null; - rules = room?.pangeaRoomRules ?? PangeaRoomRules(); + rules = room?.pangeaRoomRules ?? widget.initialRules ?? PangeaRoomRules(); super.initState(); } diff --git a/lib/pangea/utils/lock_room.dart b/lib/pangea/utils/lock_room.dart index 884ec3bad..b17fcf674 100644 --- a/lib/pangea/utils/lock_room.dart +++ b/lib/pangea/utils/lock_room.dart @@ -1,15 +1,24 @@ import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/utils/join_all_space_chats.dart'; +Future lockRoom(Room room, Client client) async { + room.isSpace ? await lockSpace(room, client) : await lockChat(room, client); +} -Future unlockChat(Room room, Client client) async { +Future unlockRoom(Room room, Client client) async { + room.isSpace + ? await unlockSpace(room, client) + : await unlockChat(room, client); +} + +Future lockChat(Room room, Client client) async { + if (!room.canChangePowerLevel) { + return; + } final Map powerLevelsContent = Map.from( room.getState(EventTypes.RoomPowerLevels)!.content, ); - - powerLevelsContent['events_default'] = 0; - powerLevelsContent['events'][EventTypes.spaceChild] = 0; + powerLevelsContent['events_default'] = 100; + powerLevelsContent['events'][EventTypes.spaceChild] = 100; await room.client.setRoomStateWithKey( room.id, @@ -19,12 +28,16 @@ Future unlockChat(Room room, Client client) async { ); } -Future lockChat(Room room, Client client) async { +Future unlockChat(Room room, Client client) async { + if (!room.canChangePowerLevel) { + return; + } final Map powerLevelsContent = Map.from( room.getState(EventTypes.RoomPowerLevels)!.content, ); - powerLevelsContent['events_default'] = 100; - powerLevelsContent['events'][EventTypes.spaceChild] = 100; + + powerLevelsContent['events_default'] = 0; + powerLevelsContent['events'][EventTypes.spaceChild] = 0; await room.client.setRoomStateWithKey( room.id, @@ -35,30 +48,33 @@ Future lockChat(Room room, Client client) async { } Future lockSpace(Room space, Client client) async { - final List children = await joinAllSpaceChats(space, client); - for (final Room child in children) { - await lockChat(child, client); + for (final spaceChild in space.spaceChildren) { + Room? child = client.getRoomById(spaceChild.roomId!); + if (child == null) { + try { + await client.joinRoom(spaceChild.roomId!); + await client.waitForRoomInSync(spaceChild.roomId!, join: true); + child = client.getRoomById(spaceChild.roomId!); + } catch (err) { + await client.leaveRoom(spaceChild.roomId!); + continue; + } + } + if (child == null) continue; + child.isSpace + ? await lockSpace(child, client) + : await lockChat(child, client); } await lockChat(space, client); } Future unlockSpace(Room space, Client client) async { - final List children = space.spaceChildren - .map((child) => client.getRoomById(child.roomId!)) - .toList(); - for (final Room? child in children) { - if (child != null) { - await unlockChat(child, client); - } + for (final spaceChild in space.spaceChildren) { + final Room? child = client.getRoomById(spaceChild.roomId!); + if (child == null) continue; + child.isSpace + ? await unlockSpace(child, client) + : await unlockChat(child, client); } await unlockChat(space, client); } - -Future toggleLockRoom(Room? room, Client client) async { - if (room == null || !room.isRoomAdmin) return; - if (!room.isSpace) { - room.locked ? await unlockChat(room, client) : await lockChat(room, client); - return; - } - room.locked ? await unlockSpace(room, client) : await lockSpace(room, client); -} diff --git a/lib/pangea/widgets/space/class_settings.dart b/lib/pangea/widgets/space/class_settings.dart index 03a139c45..15025be32 100644 --- a/lib/pangea/widgets/space/class_settings.dart +++ b/lib/pangea/widgets/space/class_settings.dart @@ -1,13 +1,12 @@ import 'dart:developer'; +import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:flutter/foundation.dart'; 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/pangea/models/class_model.dart'; import '../../../widgets/matrix.dart'; import '../../constants/language_keys.dart'; import '../../constants/language_level_type.dart'; @@ -24,8 +23,14 @@ import '../user_settings/p_question_container.dart'; class ClassSettings extends StatefulWidget { final String? roomId; final bool startOpen; + final ClassSettingsModel? initialSettings; - const ClassSettings({super.key, this.roomId, this.startOpen = false}); + const ClassSettings({ + super.key, + this.roomId, + this.startOpen = false, + this.initialSettings, + }); @override ClassSettingsState createState() => ClassSettingsState(); @@ -49,7 +54,8 @@ class ClassSettingsState extends State { ? Matrix.of(context).client.getRoomById(widget.roomId!) : null; - classSettings = room?.classSettings ?? ClassSettingsModel(); + classSettings = + room?.classSettings ?? widget.initialSettings ?? ClassSettingsModel(); isOpen = widget.startOpen; diff --git a/lib/pangea/widgets/user_settings/p_language_dialog.dart b/lib/pangea/widgets/user_settings/p_language_dialog.dart index b914212dc..077959ead 100644 --- a/lib/pangea/widgets/user_settings/p_language_dialog.dart +++ b/lib/pangea/widgets/user_settings/p_language_dialog.dart @@ -1,14 +1,15 @@ import 'dart:developer'; +import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; +import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/models/language_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; -import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; import '../../../config/themes.dart'; import '../../../widgets/matrix.dart'; import 'p_language_dropdown.dart'; @@ -17,12 +18,24 @@ import 'p_question_container.dart'; pLanguageDialog(BuildContext parentContext, Function callback) { final PangeaController pangeaController = MatrixState.pangeaController; //PTODO: if source language not set by user, default to languge from device settings - LanguageModel selectedSourceLanguage = - pangeaController.languageController.userL1 ?? - pangeaController.pLanguageStore.targetOptions[0]; - LanguageModel selectedTargetLanguage = - pangeaController.languageController.userL2 ?? - pangeaController.pLanguageStore.targetOptions[1]; + final LanguageModel? userL1 = pangeaController.languageController.userL1; + final LanguageModel? userL2 = pangeaController.languageController.userL2; + final String systemLang = Localizations.localeOf(parentContext).languageCode; + final LanguageModel systemLanguage = PangeaLanguage.byLangCode(systemLang); + + LanguageModel selectedSourceLanguage = systemLanguage; + if (userL1 != null && userL1.langCode != LanguageKeys.unknownLanguage) { + selectedSourceLanguage = userL1; + } + + LanguageModel selectedTargetLanguage; + if (userL2 != null && userL2.langCode != LanguageKeys.unknownLanguage) { + selectedTargetLanguage = userL2; + } else { + selectedTargetLanguage = selectedSourceLanguage.langCode != 'en' + ? PangeaLanguage.byLangCode('en') + : PangeaLanguage.byLangCode('es'); + } return showDialog( useRootNavigator: false, diff --git a/lib/pangea/widgets/user_settings/p_language_dropdown.dart b/lib/pangea/widgets/user_settings/p_language_dropdown.dart index 0694355c5..0793efdc2 100644 --- a/lib/pangea/widgets/user_settings/p_language_dropdown.dart +++ b/lib/pangea/widgets/user_settings/p_language_dropdown.dart @@ -1,8 +1,8 @@ // Flutter imports: +import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; import '../../widgets/flag.dart'; class PLanguageDropdown extends StatefulWidget { @@ -27,18 +27,27 @@ class _PLanguageDropdownState extends State { @override Widget build(BuildContext context) { final List sortedLanguages = widget.languages; + final String systemLang = Localizations.localeOf(context).languageCode; + final List languagePriority = [systemLang, 'en', 'es']; int sortLanguages(LanguageModel a, LanguageModel b) { - if (a.langCode == 'en') { - return -1; // "English" comes first - } else if (b.langCode == 'en') { - return 1; - } else if (a.langCode == 'es') { - return -1; // "Spanish" comes second - } else if (b.langCode == 'es') { - return 1; + final String aLang = a.langCode; + final String bLang = b.langCode; + if (aLang == bLang) return 0; + + final bool aIsPriority = languagePriority.contains(a.langCode); + final bool bIsPriority = languagePriority.contains(b.langCode); + if (!aIsPriority && !bIsPriority) { + return a.getDisplayName(context)!.compareTo(b.getDisplayName(context)!); } - return a.getDisplayName(context)!.compareTo(b.getDisplayName(context)!); + + if (aIsPriority && bIsPriority) { + final int aPriority = languagePriority.indexOf(a.langCode); + final int bPriority = languagePriority.indexOf(b.langCode); + return aPriority - bPriority; + } + + return aIsPriority ? -1 : 1; } sortedLanguages.sort((a, b) => sortLanguages(a, b)); diff --git a/needed-translations.txt b/needed-translations.txt index 12029f657..2877ad298 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -756,10 +756,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -1526,10 +1529,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -2296,10 +2302,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -3061,10 +3070,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -3826,10 +3838,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -4591,10 +4606,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -5361,10 +5379,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -6126,10 +6147,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -6155,10 +6179,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -6920,10 +6947,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -7685,10 +7715,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -8450,10 +8483,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -9215,10 +9251,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -9980,10 +10019,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -10745,10 +10787,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -11510,10 +11555,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -12275,10 +12323,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -13045,10 +13096,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -13810,10 +13864,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -14575,10 +14632,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -15340,10 +15400,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -16107,10 +16170,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -16872,10 +16938,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -17637,10 +17706,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -18402,10 +18474,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -19167,10 +19242,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -19937,10 +20015,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -20702,10 +20783,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -21467,10 +21551,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -22232,10 +22319,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -23002,10 +23092,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -23767,10 +23860,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -24532,10 +24628,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -25297,10 +25396,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -26062,10 +26164,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -26828,10 +26933,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -27596,10 +27704,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -28361,10 +28472,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -29126,10 +29240,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -29896,10 +30013,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -30666,10 +30786,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -31431,10 +31554,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -32196,10 +32322,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -32964,10 +33093,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -33729,10 +33861,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ], @@ -34494,10 +34629,13 @@ "groupName", "createGroupAndInviteUsers", "groupCanBeFoundViaSearch", + "inNoSpaces", + "createClass", + "createExchange", + "viewArchive", "trialExpiration", "freeTrialDesc", "activateTrial", - "inNoSpaces", "successfullySubscribed", "clickToManageSubscription" ]