diff --git a/assets/l10n/intl_hr.arb b/assets/l10n/intl_hr.arb index 829d19729..dcf927e7e 100644 --- a/assets/l10n/intl_hr.arb +++ b/assets/l10n/intl_hr.arb @@ -1058,10 +1058,6 @@ "type": "text", "placeholders": {} }, - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, "none": "Ništa", "@none": { "type": "text", @@ -2294,7 +2290,7 @@ "type": "text", "placeholders": {} }, - "reportErrorDescription": "Dogodila se greška. Pokušaj ponovo kasnije. Ako želiš, grešku možeš prijaviti programerima.", + "reportErrorDescription": "😭 Joj! Dogodila se greška. Pokušaj ponovo kasnije. Ako želiš, grešku možeš prijaviti programerima.", "@reportErrorDescription": {}, "signInWithPassword": "Prijavi se s lozinkom", "@signInWithPassword": {}, @@ -2392,7 +2388,7 @@ "seconds": {} } }, - "hasKnocked": "{user} je pokucao/la", + "hasKnocked": "🚪 {user} je pokucao/la", "@hasKnocked": { "placeholders": { "user": {} @@ -2400,17 +2396,10 @@ }, "pleaseEnterANumber": "Upiši broj veći od 0", "@pleaseEnterANumber": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@unbanUserDescription": {}, "pushNotificationsNotAvailable": "Automatsko slanje obavijesti nije dostupno", "@pushNotificationsNotAvailable": {}, - "@makeAdminDescription": {}, - "@archiveRoomDescription": {}, "learnMore": "Saznaj više", "@learnMore": {}, - "@roomUpgradeDescription": {}, - "@kickUserDescription": {}, "createGroupAndInviteUsers": "Stvori grupu i pozovi korisnike", "@createGroupAndInviteUsers": {}, "startConversation": "Pokreni konverzaciju", @@ -2419,7 +2408,7 @@ "@blockedUsers": {}, "groupCanBeFoundViaSearch": "Grupa se može pronaći putem pretrage", "@groupCanBeFoundViaSearch": {}, - "block": "blokiraj", + "block": "Blokiraj", "@block": {}, "yourGlobalUserIdIs": "Tvoj globalni korisnički ID je: ", "@yourGlobalUserIdIs": {}, @@ -2436,5 +2425,29 @@ "searchChatsRooms": "Traži #chats, @users …", "@searchChatsRooms": {}, "databaseMigrationBody": "Pričekaj. Ovo može potrajati.", - "@databaseMigrationBody": {} + "@databaseMigrationBody": {}, + "transparent": "Prozirno", + "@transparent": {}, + "formattedMessages": "Formatirane poruke", + "@formattedMessages": {}, + "incomingMessages": "Dolazne poruke", + "@incomingMessages": {}, + "passwordsDoNotMatch": "Lozinke se ne poklapaju", + "@passwordsDoNotMatch": {}, + "accessAndVisibility": "Pristup i vidljivost", + "@accessAndVisibility": {}, + "calls": "Pozivi", + "@calls": {}, + "customEmojisAndStickers": "Prilagođeni emojiji i naljepnice", + "@customEmojisAndStickers": {}, + "customEmojisAndStickersBody": "Dodaj ili dijeli prilagođene emojije ili naljepnice koje se mogu koristiti u bilo kojem razgovoru.", + "@customEmojisAndStickersBody": {}, + "accessAndVisibilityDescription": "Tko se smije pridružiti ovom razgovoru i kako se razgovor može otkriti.", + "@accessAndVisibilityDescription": {}, + "stickers": "Naljepnice", + "@stickers": {}, + "discover": "Otkrij", + "@discover": {}, + "formattedMessagesDescription": "Prikaži formatirani sadržaj poruke poput podebljanog teksta koristeći markdown.", + "@formattedMessagesDescription": {} } diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 46f568373..fb84bae63 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -969,7 +969,7 @@ class ChatController extends State ); } for (final event in selectedEvents) { - await event.remove(); + await event.cancelSend(); } setState(selectedEvents.clear); } catch (e, s) { @@ -1019,7 +1019,7 @@ class ChatController extends State ); } } else { - await event.remove(); + await event.cancelSend(); } }, ); diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index f914344ab..61f9e1065 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -58,22 +58,6 @@ class HtmlMessage extends StatelessWidget { @override Widget build(BuildContext context) { - // riot-web is notorious for creating bad reply fallback events from invalid messages which, if - // not handled properly, can lead to impersination. As such, we strip the entire `` tags - // here already, to prevent that from happening. - // We do *not* do this in an AST and just with simple regex here, as riot-web tends to create - // miss-matching tags, and this way we actually correctly identify what we want to strip and, well, - // strip it. - final renderHtml = html.replaceAll( - RegExp( - '.*', - caseSensitive: false, - multiLine: false, - dotAll: true, - ), - '', - ); - final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; final linkColor = textColor.withAlpha(150); @@ -88,7 +72,7 @@ class HtmlMessage extends StatelessWidget { padding: HtmlPaddings.only(left: 6, bottom: 0), ); - final element = _linkifyHtml(HtmlParser.parseHTML(renderHtml)); + final element = _linkifyHtml(HtmlParser.parseHTML(html)); // there is no need to pre-validate the html, as we validate it while rendering // #Pangea diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 55161b9b6..2866e3260 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -7,7 +7,6 @@ import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; import 'package:fluffychat/pangea/widgets/chat_list/chat_list_body_text.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; @@ -40,7 +39,7 @@ class ChatListViewBody extends StatelessWidget { Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(100); final subtitleColor = Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(50); - + final filter = controller.searchController.text.toLowerCase(); return PageTransitionSwitcher( transitionBuilder: ( Widget child, @@ -245,35 +244,23 @@ class ChatListViewBody extends StatelessWidget { ), ), if (client.prevBatch != null) - SliverList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int i) { - if (!rooms[i] - .getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ) - .toLowerCase() - .contains( - controller.searchController.text.toLowerCase(), - )) { - return const SizedBox.shrink(); - } - final activeChat = controller.activeChat == rooms[i].id; - return ChatListItem( - rooms[i], - key: Key('chat_list_item_${rooms[i].id}'), - selected: - controller.selectedRoomIds.contains(rooms[i].id), - onTap: controller.selectMode == SelectMode.select - ? () => controller.toggleSelection(rooms[i].id) - : () => onChatTap(rooms[i], context), - onLongPress: () => - controller.toggleSelection(rooms[i].id), - activeChat: activeChat, - ); - }, - childCount: rooms.length, - ), + SliverList.builder( + itemCount: rooms.length, + itemBuilder: (BuildContext context, int i) { + return ChatListItem( + rooms[i], + key: Key('chat_list_item_${rooms[i].id}'), + filter: filter, + selected: + controller.selectedRoomIds.contains(rooms[i].id), + onTap: controller.selectMode == SelectMode.select + ? () => controller.toggleSelection(rooms[i].id) + : () => onChatTap(rooms[i], context), + onLongPress: () => + controller.toggleSelection(rooms[i].id), + activeChat: controller.activeChat == rooms[i].id, + ); + }, ), ], ), diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index e53a0cff4..0dabf9d0a 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -94,11 +94,6 @@ class ChatListItem extends StatelessWidget { if (filter != null && !displayname.toLowerCase().contains(filter)) { return const SizedBox.shrink(); } - - final needLastEventSender = lastEvent == null - ? false - : room.getState(EventTypes.RoomMember, lastEvent.senderId) == null; - return Padding( padding: const EdgeInsets.symmetric( horizontal: 8, @@ -239,21 +234,20 @@ class ChatListItem extends StatelessWidget { maxLines: 1, softWrap: false, ) - : FutureBuilder( - key: ValueKey(lastEvent?.eventId), + : FutureBuilder( // #Pangea - // future: needLastEventSender - // ? lastEvent.calcLocalizedBody( - // MatrixLocals(L10n.of(context)!), - // hideReply: true, - // hideEdit: true, - // plaintextBody: true, - // removeMarkdown: true, - // withSenderNamePrefix: !isDirectChat || - // directChatMatrixId != - // room.lastEvent?.senderId, - // ) - // : null, + // future: room.lastEvent?.calcLocalizedBody( + // MatrixLocals(L10n.of(context)!), + // hideReply: true, + // hideEdit: true, + // plaintextBody: true, + // removeMarkdown: true, + // withSenderNamePrefix: !isDirectChat || + // directChatMatrixId != + // room.lastEvent?.senderId, + // ) ?? + // Future.value(L10n.of(context)!.emptyChat), + // Pangea# future: room.lastEvent != null ? GetChatListItemSubtitle().getSubtitle( L10n.of(context)!, @@ -261,37 +255,39 @@ class ChatListItem extends StatelessWidget { MatrixState.pangeaController, ) : Future.value(L10n.of(context)!.emptyChat), - // Pangea# - initialData: lastEvent?.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)!), - hideReply: true, - hideEdit: true, - plaintextBody: true, - removeMarkdown: true, - withSenderNamePrefix: !isDirectChat || - directChatMatrixId != - room.lastEvent?.senderId, - ), - builder: (context, snapshot) => Text( - room.membership == Membership.invite - ? isDirectChat - ? L10n.of(context)!.invitePrivateChat - : L10n.of(context)!.inviteGroupChat - : snapshot.data ?? - L10n.of(context)!.emptyChat, - softWrap: false, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: unread || room.hasNewMessages - ? FontWeight.bold - : null, - color: theme.colorScheme.onSurfaceVariant, - decoration: room.lastEvent?.redacted == true - ? TextDecoration.lineThrough - : null, - ), - ), + builder: (context, snapshot) { + return Text( + room.membership == Membership.invite + ? isDirectChat + ? L10n.of(context)!.invitePrivateChat + : L10n.of(context)!.inviteGroupChat + : snapshot.data ?? + room.lastEvent + ?.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)!), + hideReply: true, + hideEdit: true, + plaintextBody: true, + removeMarkdown: true, + withSenderNamePrefix: !isDirectChat || + directChatMatrixId != + room.lastEvent?.senderId, + ) ?? + L10n.of(context)!.emptyChat, + softWrap: false, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: unread || room.hasNewMessages + ? FontWeight.bold + : null, + color: theme.colorScheme.onSurfaceVariant, + decoration: room.lastEvent?.redacted == true + ? TextDecoration.lineThrough + : null, + ), + ); + }, ), ), const SizedBox(width: 8), diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 10ed00edd..fa2841464 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -30,13 +30,13 @@ class ChatListView extends StatelessWidget { badgePosition: badgePosition, filter: controller.getRoomFilterByActiveFilter(ActiveFilter.messages), - child: const Icon(Icons.forum_outlined), + child: const Icon(Icons.chat_outlined), ), selectedIcon: UnreadRoomsBadge( badgePosition: badgePosition, filter: controller.getRoomFilterByActiveFilter(ActiveFilter.messages), - child: const Icon(Icons.forum), + child: const Icon(Icons.chat), ), //#Pangea // label: L10n.of(context)!.messages, @@ -62,13 +62,13 @@ class ChatListView extends StatelessWidget { badgePosition: badgePosition, filter: controller.getRoomFilterByActiveFilter(ActiveFilter.allChats), - child: const Icon(Icons.forum_outlined), + child: const Icon(Icons.chat_outlined), ), selectedIcon: UnreadRoomsBadge( badgePosition: badgePosition, filter: controller.getRoomFilterByActiveFilter(ActiveFilter.allChats), - child: const Icon(Icons.forum), + child: const Icon(Icons.chat), ), // #Pangea // label: L10n.of(context)!.chats, @@ -222,8 +222,7 @@ class ChatListView extends StatelessWidget { ? NavigationBar( elevation: 4, labelBehavior: - NavigationDestinationLabelBehavior.alwaysHide, - height: 64, + NavigationDestinationLabelBehavior.alwaysShow, shadowColor: Theme.of(context).colorScheme.onSurface, surfaceTintColor: diff --git a/lib/pages/settings_multiple_emotes/settings_multiple_emotes_view.dart b/lib/pages/settings_multiple_emotes/settings_multiple_emotes_view.dart index 8d62549c7..939263fd3 100644 --- a/lib/pages/settings_multiple_emotes/settings_multiple_emotes_view.dart +++ b/lib/pages/settings_multiple_emotes/settings_multiple_emotes_view.dart @@ -25,9 +25,9 @@ class MultipleEmotesSettingsView extends StatelessWidget { builder: (context, snapshot) { final packStateEvents = room.states['im.ponies.room_emotes']; // we need to manually convert the map using Map.of, otherwise assigning null will throw a type error. - final Map packs = packStateEvents != null - ? Map.of(packStateEvents) - : {}; + final packs = packStateEvents != null + ? Map.of(packStateEvents) + : {}; if (!packs.containsKey('')) { packs[''] = null; } diff --git a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart index 6e0413da3..7446aebc7 100644 --- a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart +++ b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart @@ -127,11 +127,12 @@ class UserBottomSheetController extends State { textFields: [DialogTextField(hintText: L10n.of(context)!.reason)], ); if (reason == null || reason.single.isEmpty) return; + final result = await showFutureLoadingDialog( context: context, future: () => Matrix.of(widget.outerContext).client.reportContent( - user.roomId!, - user.eventId, + user.room.id, + user.id, reason: reason.single, score: score, ), diff --git a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart index c02fa9230..44423d90f 100644 --- a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart @@ -60,7 +60,10 @@ extension ClassAndExchangeSettingsRoomExtension on Room { if (ownPowerLevel < ClassDefaultValues.powerLevelOfAdmin) { return; } - final Event? currentPower = getState(EventTypes.RoomPowerLevels); + final dynamic currentPower = getState(EventTypes.RoomPowerLevels); + if (currentPower is! Event?) { + return; + } final Map? currentPowerContent = currentPower?.content["events"] as Map?; final spaceChildPower = currentPowerContent?[EventTypes.SpaceChild]; @@ -113,10 +116,21 @@ extension ClassAndExchangeSettingsRoomExtension on Room { } } - Event? get _languageSettingsStateEvent => - getState(PangeaEventTypes.classSettings); + Event? get _languageSettingsStateEvent { + final dynamic classSettings = getState(PangeaEventTypes.classSettings); + if (classSettings is Event) { + return classSettings; + } + return null; + } - Event? get _pangeaRoomRulesStateEvent => getState(PangeaEventTypes.rules); + Event? get _pangeaRoomRulesStateEvent { + final dynamic roomRules = getState(PangeaEventTypes.rules); + if (roomRules is Event) { + return roomRules; + } + return null; + } ClassSettingsModel? get _firstLanguageSettings => classSettings ?? diff --git a/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart index 213d3c4ce..e204e3f83 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart @@ -12,8 +12,11 @@ extension RoomInformationRoomExtension on Room { .length; } - DateTime? get _creationTime => - getState(EventTypes.RoomCreate)?.originServerTs; + DateTime? get _creationTime { + final dynamic roomCreate = getState(EventTypes.RoomCreate); + if (roomCreate is! Event) return null; + return roomCreate.originServerTs; + } String? get _creatorId => getState(EventTypes.RoomCreate)?.senderId; diff --git a/needed-translations.txt b/needed-translations.txt index cbd1fb0d0..83e2c8509 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -21407,11 +21407,6 @@ "createNewGroup", "editChatPermissions", "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", "enterAGroupName", "enterASpacepName", "groupDescription", @@ -22210,7 +22205,6 @@ "pleaseEnterYourCurrentPassword", "newPassword", "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", "passwordIsWrong", "publicLink", "publicChatAddresses", @@ -22255,8 +22249,6 @@ "sendReadReceipts", "sendTypingNotificationsDescription", "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", "verifyOtherUser", "verifyOtherUserDescription", "verifyOtherDevice", @@ -22287,10 +22279,6 @@ "refresh", "autoPlayTitle", "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", "commandHint_ignore", "commandHint_unignore", "unreadChatsInApp", diff --git a/pubspec.lock b/pubspec.lock index 3f23f4cfe..2667b83d9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1409,10 +1409,10 @@ packages: dependency: "direct main" description: name: matrix - sha256: "32c21a2ac2c221ce887b00a87f965bd8df1a3a4ba8794bbe86be8b56214051fb" + sha256: b9aa3c1bdb1ca16c2365bb3681f861eeeb86acd0ea2df9c9ba453fdbcb564076 url: "https://pub.dev" source: hosted - version: "0.28.1" + version: "0.29.1" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 281edaa5a..1fefa5b4e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -70,7 +70,7 @@ dependencies: keyboard_shortcuts: ^0.1.4 latlong2: ^0.9.1 linkify: ^5.0.0 - matrix: ^0.28.1 + matrix: ^0.29.1 native_imaging: ^0.1.0 package_info_plus: ^6.0.0 pasteboard: ^0.2.0