From fdb0e0c17bee1102711929971704df813cd13fa3 Mon Sep 17 00:00:00 2001 From: Lenni <87639068+Lenni-builder@users.noreply.github.com> Date: Thu, 10 Apr 2025 08:42:39 +0200 Subject: [PATCH 01/20] chore: Correct availability of desktop builds --- PRIVACY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PRIVACY.md b/PRIVACY.md index 018b85760..439899d0e 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,6 +1,6 @@ # Privacy -FluffyChat is available on Android, iOS and as a web version. Desktop versions for Windows, Linux and macOS may follow. +FluffyChat is available on Android, iOS, Linux and as a web version. Desktop versions for Windows and macOS may follow. * [Matrix](#matrix) * [Database](#database) @@ -109,4 +109,4 @@ To enhance user safety and help protect against the sexual abuse and exploitatio In addition to reporting messages, users can also report other users following a similar process. -We encourage server administrators to adhere to strict safety standards and provide mechanisms for addressing and moderating inappropriate content. For more information on the Matrix protocol and its safety standards, please refer to the following link: https://matrix.org/docs/older/moderation/ \ No newline at end of file +We encourage server administrators to adhere to strict safety standards and provide mechanisms for addressing and moderating inappropriate content. For more information on the Matrix protocol and its safety standards, please refer to the following link: https://matrix.org/docs/older/moderation/ From 2873a047f878cb52acd36bf8e97bf717f935adf5 Mon Sep 17 00:00:00 2001 From: Krille Date: Sun, 13 Apr 2025 10:38:09 +0200 Subject: [PATCH 02/20] chore: Follow up permissions slider dialog Signed-off-by: Krille --- lib/widgets/permission_slider_dialog.dart | 41 +++++++++++------------ 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/widgets/permission_slider_dialog.dart b/lib/widgets/permission_slider_dialog.dart index 0d2d365ea..c31ee433f 100644 --- a/lib/widgets/permission_slider_dialog.dart +++ b/lib/widgets/permission_slider_dialog.dart @@ -1,9 +1,7 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; - import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/dialog_text_field.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; Future showPermissionChooser( BuildContext context, { @@ -17,25 +15,24 @@ Future showPermissionChooser( builder: (context) => AlertDialog.adaptive( title: Text(L10n.of(context).chatPermissions), content: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - spacing: 12.0, - children: [ - Text(L10n.of(context).setPermissionsLevelDescription), - ValueListenableBuilder( - valueListenable: error, - builder: (context, errorText, _) => DialogTextField( - controller: controller, - hintText: currentLevel.toString(), - keyboardType: TextInputType.number, - labelText: L10n.of(context).custom, - errorText: errorText, - ), + constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 12.0, + children: [ + Text(L10n.of(context).setPermissionsLevelDescription), + ValueListenableBuilder( + valueListenable: error, + builder: (context, errorText, _) => DialogTextField( + controller: controller, + hintText: currentLevel.toString(), + keyboardType: TextInputType.number, + labelText: L10n.of(context).custom, + errorText: errorText, ), - ], - ), + ), + ], ), ), actions: [ From 3594fa4f6dc640e34a9cb4c226a8e48409b69020 Mon Sep 17 00:00:00 2001 From: Krille Date: Sun, 13 Apr 2025 11:04:52 +0200 Subject: [PATCH 03/20] refactor: Implement avatar image viewer and adjust design Signed-off-by: Krille --- lib/pages/bootstrap/bootstrap_dialog.dart | 5 +- lib/pages/chat/events/html_message.dart | 2 +- lib/pages/chat/input_bar.dart | 4 +- lib/pages/chat_details/chat_details_view.dart | 9 ++ .../chat_encryption_settings_view.dart | 2 +- lib/pages/settings/settings_view.dart | 11 ++- .../settings_security_view.dart | 3 +- lib/utils/string_color.dart | 4 +- lib/widgets/adaptive_dialogs/user_dialog.dart | 85 +++++++++++-------- lib/widgets/avatar.dart | 19 ++--- lib/widgets/mxc_image_viewer.dart | 60 +++++++++++++ lib/widgets/permission_slider_dialog.dart | 6 +- 12 files changed, 151 insertions(+), 59 deletions(-) create mode 100644 lib/widgets/mxc_image_viewer.dart diff --git a/lib/pages/bootstrap/bootstrap_dialog.dart b/lib/pages/bootstrap/bootstrap_dialog.dart index c2f35fc78..61441eb6d 100644 --- a/lib/pages/bootstrap/bootstrap_dialog.dart +++ b/lib/pages/bootstrap/bootstrap_dialog.dart @@ -18,6 +18,7 @@ import '../key_verification/key_verification_dialog.dart'; class BootstrapDialog extends StatefulWidget { final bool wipe; final Client client; + const BootstrapDialog({ super.key, this.wipe = false, @@ -132,7 +133,7 @@ class BootstrapDialogState extends State { minLines: 2, maxLines: 4, readOnly: true, - style: const TextStyle(fontFamily: 'UbuntuMono'), + style: const TextStyle(fontFamily: 'RobotoMono'), controller: TextEditingController(text: key), decoration: const InputDecoration( contentPadding: EdgeInsets.all(16), @@ -257,7 +258,7 @@ class BootstrapDialogState extends State { ? null : [AutofillHints.password], controller: _recoveryKeyTextEditingController, - style: const TextStyle(fontFamily: 'UbuntuMono'), + style: const TextStyle(fontFamily: 'RobotoMono'), decoration: InputDecoration( contentPadding: const EdgeInsets.all(16), hintStyle: TextStyle( diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index f093d1090..d40ac72a7 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -295,7 +295,7 @@ class HtmlMessage extends StatelessWidget { ), textStyle: TextStyle( fontSize: fontSize, - fontFamily: 'UbuntuMono', + fontFamily: 'RobotoMono', ), ), ), diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 42b88b0b7..7be7a3c7d 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -235,7 +235,7 @@ class InputBar extends StatelessWidget { children: [ Text( commandExample(command), - style: const TextStyle(fontFamily: 'UbuntuMono'), + style: const TextStyle(fontFamily: 'RobotoMono'), ), Text( hint, @@ -255,7 +255,7 @@ class InputBar extends StatelessWidget { waitDuration: const Duration(days: 1), // don't show on hover child: Container( padding: padding, - child: Text(label, style: const TextStyle(fontFamily: 'UbuntuMono')), + child: Text(label, style: const TextStyle(fontFamily: 'RobotoMono')), ), ); } diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index d368f0211..e96c10d82 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -14,6 +14,7 @@ import 'package:fluffychat/widgets/chat_settings_popup_menu.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/matrix.dart'; import '../../utils/url_launcher.dart'; +import '../../widgets/mxc_image_viewer.dart'; import '../../widgets/qr_code_viewer.dart'; class ChatDetailsView extends StatelessWidget { @@ -38,6 +39,7 @@ class ChatDetailsView extends StatelessWidget { } final directChatMatrixID = room.directChatMatrixID; + final roomAvatar = room.avatar; return StreamBuilder( stream: room.client.onRoomState.stream @@ -108,6 +110,13 @@ class ChatDetailsView extends StatelessWidget { mxContent: room.avatar, name: displayname, size: Avatar.defaultSize * 2.5, + onTap: roomAvatar != null + ? () => showDialog( + context: context, + builder: (_) => + MxcImageViewer(roomAvatar), + ) + : null, ), ), if (!room.isDirectChat && diff --git a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart index 4a61facbc..2c39a942e 100644 --- a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart +++ b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart @@ -169,7 +169,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { deviceKeys[i].ed25519Key?.beautified ?? L10n.of(context).unknownEncryptionAlgorithm, style: TextStyle( - fontFamily: 'UbuntuMono', + fontFamily: 'RobotoMono', color: theme.colorScheme.secondary, ), ), diff --git a/lib/pages/settings/settings_view.dart b/lib/pages/settings/settings_view.dart index baa719550..eddbc76e8 100644 --- a/lib/pages/settings/settings_view.dart +++ b/lib/pages/settings/settings_view.dart @@ -12,6 +12,7 @@ import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/navigation_rail.dart'; +import '../../widgets/mxc_image_viewer.dart'; import 'settings.dart'; class SettingsView extends StatelessWidget { @@ -65,6 +66,7 @@ class SettingsView extends StatelessWidget { future: controller.profileFuture, builder: (context, snapshot) { final profile = snapshot.data; + final avatar = profile?.avatarUrl; final mxid = Matrix.of(context).client.userID ?? L10n.of(context).user; final displayname = @@ -76,9 +78,16 @@ class SettingsView extends StatelessWidget { child: Stack( children: [ Avatar( - mxContent: profile?.avatarUrl, + mxContent: avatar, name: displayname, size: Avatar.defaultSize * 2.5, + onTap: avatar != null + ? () => showDialog( + context: context, + builder: (_) => + MxcImageViewer(avatar), + ) + : null, ), if (profile != null) Positioned( diff --git a/lib/pages/settings_security/settings_security_view.dart b/lib/pages/settings_security/settings_security_view.dart index 0861f1351..5d729091d 100644 --- a/lib/pages/settings_security/settings_security_view.dart +++ b/lib/pages/settings_security/settings_security_view.dart @@ -16,6 +16,7 @@ import 'settings_security.dart'; class SettingsSecurityView extends StatelessWidget { final SettingsSecurityController controller; + const SettingsSecurityView(this.controller, {super.key}); @override @@ -143,7 +144,7 @@ class SettingsSecurityView extends StatelessWidget { leading: const Icon(Icons.vpn_key_outlined), subtitle: SelectableText( Matrix.of(context).client.fingerprintKey.beautified, - style: const TextStyle(fontFamily: 'UbuntuMono'), + style: const TextStyle(fontFamily: 'RobotoMono'), ), ), if (capabilities?.mChangePassword?.enabled != false || diff --git a/lib/utils/string_color.dart b/lib/utils/string_color.dart index d854d1527..a0dfbf5c0 100644 --- a/lib/utils/string_color.dart +++ b/lib/utils/string_color.dart @@ -9,7 +9,7 @@ extension StringColor on String { number += codeUnitAt(i); } number = (number % 12) * 25.5; - return HSLColor.fromAHSL(1, number, 1, light).toColor(); + return HSLColor.fromAHSL(0.75, number, 1, light).toColor(); } Color get color { @@ -29,6 +29,6 @@ extension StringColor on String { Color get lightColorAvatar { _colorCache[this] ??= {}; - return _colorCache[this]![0.4] ??= _getColorLight(0.4); + return _colorCache[this]![0.45] ??= _getColorLight(0.45); } } diff --git a/lib/widgets/adaptive_dialogs/user_dialog.dart b/lib/widgets/adaptive_dialogs/user_dialog.dart index 5d17dd791..34fe1739f 100644 --- a/lib/widgets/adaptive_dialogs/user_dialog.dart +++ b/lib/widgets/adaptive_dialogs/user_dialog.dart @@ -15,6 +15,7 @@ import '../../utils/url_launcher.dart'; import '../future_loading_dialog.dart'; import '../hover_builder.dart'; import '../matrix.dart'; +import '../mxc_image_viewer.dart'; class UserDialog extends StatelessWidget { static Future show({ @@ -45,6 +46,7 @@ class UserDialog extends StatelessWidget { L10n.of(context).user; var copied = false; final theme = Theme.of(context); + final avatar = profile.avatarUrl; return AlertDialog.adaptive( title: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256), @@ -75,54 +77,65 @@ class UserDialog extends StatelessWidget { children: [ HoverBuilder( builder: (context, hovered) => StatefulBuilder( - builder: (context, setState) => GestureDetector( - onTap: () { - Clipboard.setData( - ClipboardData(text: profile.userId), - ); - setState(() { - copied = true; - }); - }, - child: RichText( - text: TextSpan( - children: [ - WidgetSpan( - child: Padding( - padding: const EdgeInsets.only(right: 4.0), - child: AnimatedScale( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - scale: hovered - ? 1.33 - : copied - ? 1.25 - : 1.0, - child: Icon( - copied - ? Icons.check_circle - : Icons.copy, - size: 12, - color: copied ? Colors.green : null, + builder: (context, setState) => MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + Clipboard.setData( + ClipboardData(text: profile.userId), + ); + setState(() { + copied = true; + }); + }, + child: RichText( + text: TextSpan( + children: [ + WidgetSpan( + child: Padding( + padding: + const EdgeInsets.only(right: 4.0), + child: AnimatedScale( + duration: + FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: hovered + ? 1.33 + : copied + ? 1.25 + : 1.0, + child: Icon( + copied + ? Icons.check_circle + : Icons.copy, + size: 12, + color: copied ? Colors.green : null, + ), ), ), ), - ), - TextSpan(text: profile.userId), - ], - style: theme.textTheme.bodyMedium - ?.copyWith(fontSize: 10), + TextSpan(text: profile.userId), + ], + style: theme.textTheme.bodyMedium + ?.copyWith(fontSize: 10), + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, ), ), ), ), Center( child: Avatar( - mxContent: profile.avatarUrl, + mxContent: avatar, name: displayname, size: Avatar.defaultSize * 2, + onTap: avatar != null + ? () => showDialog( + context: context, + builder: (_) => MxcImageViewer(avatar), + ) + : null, ), ), if (presenceText != null) diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 17668b2be..0a60c1b4a 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -62,18 +62,13 @@ class Avatar extends StatelessWidget { clipBehavior: Clip.hardEdge, child: noPic ? Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [name!.lightColorAvatar, name.color], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), + decoration: BoxDecoration(color: name!.lightColorAvatar), alignment: Alignment.center, child: Text( fallbackLetters, textAlign: TextAlign.center, style: TextStyle( + fontFamily: 'RobotoMono', color: Colors.white, fontWeight: FontWeight.bold, fontSize: (size / 2.5).roundToDouble(), @@ -143,10 +138,12 @@ class Avatar extends StatelessWidget { ], ); if (onTap == null) return container; - return InkWell( - onTap: onTap, - borderRadius: borderRadius, - child: container, + return MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: onTap, + child: container, + ), ); } } diff --git a/lib/widgets/mxc_image_viewer.dart b/lib/widgets/mxc_image_viewer.dart new file mode 100644 index 000000000..334f28224 --- /dev/null +++ b/lib/widgets/mxc_image_viewer.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +import 'mxc_image.dart'; + +class MxcImageViewer extends StatelessWidget { + final Uri mxContent; + + const MxcImageViewer(this.mxContent, {super.key}); + + @override + Widget build(BuildContext context) { + final iconButtonStyle = IconButton.styleFrom( + backgroundColor: Colors.black.withAlpha(200), + foregroundColor: Colors.white, + ); + return GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: Scaffold( + backgroundColor: Colors.black.withAlpha(128), + extendBodyBehindAppBar: true, + appBar: AppBar( + elevation: 0, + leading: IconButton( + style: iconButtonStyle, + icon: const Icon(Icons.close), + onPressed: Navigator.of(context).pop, + color: Colors.white, + tooltip: L10n.of(context).close, + ), + backgroundColor: Colors.transparent, + ), + body: InteractiveViewer( + minScale: 1.0, + maxScale: 10.0, + onInteractionEnd: (endDetails) { + if (endDetails.velocity.pixelsPerSecond.dy > + MediaQuery.of(context).size.height * 1.5) { + Navigator.of(context, rootNavigator: false).pop(); + } + }, + child: Center( + child: GestureDetector( + // Ignore taps to not go back here: + onTap: () {}, + child: MxcImage( + key: ValueKey(mxContent.toString()), + uri: mxContent, + fit: BoxFit.contain, + isThumbnail: false, + animated: true, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/permission_slider_dialog.dart b/lib/widgets/permission_slider_dialog.dart index c31ee433f..fff6685e9 100644 --- a/lib/widgets/permission_slider_dialog.dart +++ b/lib/widgets/permission_slider_dialog.dart @@ -1,8 +1,10 @@ -import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; -import 'package:fluffychat/widgets/adaptive_dialogs/dialog_text_field.dart'; import 'package:flutter/material.dart'; + import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/dialog_text_field.dart'; + Future showPermissionChooser( BuildContext context, { int currentLevel = 0, From 5e7b0bf7247e053d15bd44fe5aa013d43bc7dfa6 Mon Sep 17 00:00:00 2001 From: Krille Date: Sun, 13 Apr 2025 13:11:14 +0200 Subject: [PATCH 04/20] feat: Filter for room members page and easier approve knocking users Signed-off-by: Krille --- assets/l10n/intl_en.arb | 3 +- lib/config/themes.dart | 8 ++ .../chat_details/participant_list_item.dart | 105 +++++++++--------- lib/pages/chat_list/chat_list_body.dart | 59 ++-------- lib/pages/chat_members/chat_members.dart | 43 ++++++- lib/pages/chat_members/chat_members_view.dart | 102 +++++++++++++---- .../member_actions_popup_menu_button.dart | 21 +++- 7 files changed, 215 insertions(+), 126 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 49a1734f0..73ccd9a9c 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3211,5 +3211,6 @@ "recordAVideo": "Record a video", "optionalMessage": "(Optional) message...", "notSupportedOnThisDevice": "Not supported on this device", - "enterNewChat": "Enter new chat" + "enterNewChat": "Enter new chat", + "approve": "Approve" } diff --git a/lib/config/themes.dart b/lib/config/themes.dart index d2a151c3b..826f6440a 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -75,6 +75,14 @@ abstract class FluffyThemes { ), contentPadding: const EdgeInsets.all(12), ), + chipTheme: ChipThemeData( + showCheckmark: false, + backgroundColor: colorScheme.surfaceContainer, + side: BorderSide.none, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + ), + ), appBarTheme: AppBarTheme( toolbarHeight: isColumnMode ? 72 : 56, shadowColor: diff --git a/lib/pages/chat_details/participant_list_item.dart b/lib/pages/chat_details/participant_list_item.dart index 365c7bcf8..ec90fcf54 100644 --- a/lib/pages/chat_details/participant_list_item.dart +++ b/lib/pages/chat_details/participant_list_item.dart @@ -30,65 +30,68 @@ class ParticipantListItem extends StatelessWidget { ? L10n.of(context).moderator : ''; - return Opacity( - opacity: user.membership == Membership.join ? 1 : 0.5, - child: ListTile( - onTap: () => showMemberActionsPopupMenu(context: context, user: user), - title: Row( - children: [ - Expanded( - child: Text( - user.calcDisplayname(), - overflow: TextOverflow.ellipsis, - ), + return ListTile( + onTap: () => showMemberActionsPopupMenu(context: context, user: user), + title: Row( + children: [ + Expanded( + child: Text( + user.calcDisplayname(), + overflow: TextOverflow.ellipsis, ), - if (permissionBatch.isNotEmpty) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, + ), + if (permissionBatch.isNotEmpty) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: user.powerLevel >= 100 + ? theme.colorScheme.tertiary + : theme.colorScheme.tertiaryContainer, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), - decoration: BoxDecoration( + ), + child: Text( + permissionBatch, + style: theme.textTheme.labelSmall?.copyWith( color: user.powerLevel >= 100 - ? theme.colorScheme.tertiary - : theme.colorScheme.tertiaryContainer, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ), - child: Text( - permissionBatch, - style: theme.textTheme.labelSmall?.copyWith( - color: user.powerLevel >= 100 - ? theme.colorScheme.onTertiary - : theme.colorScheme.onTertiaryContainer, - ), + ? theme.colorScheme.onTertiary + : theme.colorScheme.onTertiaryContainer, ), ), - membershipBatch == null - ? const SizedBox.shrink() - : Container( - padding: const EdgeInsets.all(4), - margin: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - color: theme.secondaryHeaderColor, - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - membershipBatch, - style: theme.textTheme.labelSmall, + ), + membershipBatch == null + ? const SizedBox.shrink() + : Container( + padding: + const EdgeInsets.symmetric(vertical: 4, horizontal: 8), + margin: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: theme.colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(8), + ), + child: Center( + child: Text( + membershipBatch, + style: theme.textTheme.labelSmall?.copyWith( + color: theme.colorScheme.onSecondaryContainer, ), ), ), - ], - ), - subtitle: Text( - user.id, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - leading: Avatar( + ), + ], + ), + subtitle: Text( + user.id, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + leading: Opacity( + opacity: user.membership == Membership.join ? 1 : 0.5, + child: Avatar( mxContent: user.avatarUrl, name: user.calcDisplayname(), presenceUserId: user.stateKey, diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 59bec1e6f..af19d17c8 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -14,7 +14,6 @@ import 'package:fluffychat/pages/chat_list/status_msg_list.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/hover_builder.dart'; import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; import '../../config/themes.dart'; import '../../widgets/adaptive_dialogs/user_dialog.dart'; @@ -155,7 +154,7 @@ class ChatListViewBody extends StatelessWidget { child: ListView( padding: const EdgeInsets.symmetric( horizontal: 12.0, - vertical: 16.0, + vertical: 12.0, ), shrinkWrap: true, scrollDirection: Axis.horizontal, @@ -172,53 +171,15 @@ class ChatListViewBody extends StatelessWidget { ] .map( (filter) => Padding( - padding: - const EdgeInsets.symmetric(horizontal: 4), - child: HoverBuilder( - builder: (context, hovered) => - AnimatedScale( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - scale: hovered ? 1.1 : 1.0, - child: InkWell( - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - onTap: () => - controller.setActiveFilter(filter), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), - decoration: BoxDecoration( - color: filter == - controller.activeFilter - ? theme.colorScheme.primary - : theme.colorScheme - .secondaryContainer, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ), - alignment: Alignment.center, - child: Text( - filter.toLocalizedString(context), - style: TextStyle( - fontWeight: filter == - controller.activeFilter - ? FontWeight.w500 - : FontWeight.normal, - color: filter == - controller.activeFilter - ? theme.colorScheme.onPrimary - : theme.colorScheme - .onSecondaryContainer, - ), - ), - ), - ), - ), + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + ), + child: FilterChip( + selected: filter == controller.activeFilter, + onSelected: (_) => + controller.setActiveFilter(filter), + label: + Text(filter.toLocalizedString(context)), ), ), ) diff --git a/lib/pages/chat_members/chat_members.dart b/lib/pages/chat_members/chat_members.dart index c777d286e..d1ab81a5a 100644 --- a/lib/pages/chat_members/chat_members.dart +++ b/lib/pages/chat_members/chat_members.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -7,6 +9,7 @@ import 'chat_members_view.dart'; class ChatMembersPage extends StatefulWidget { final String roomId; + const ChatMembersPage({required this.roomId, super.key}); @override @@ -17,12 +20,27 @@ class ChatMembersController extends State { List? members; List? filteredMembers; Object? error; + Membership membershipFilter = Membership.join; final TextEditingController filterController = TextEditingController(); + void setMembershipFilter(Membership membership) { + membershipFilter = membership; + setFilter(); + } + void setFilter([_]) async { final filter = filterController.text.toLowerCase().trim(); + final members = this + .members + ?.where( + (member) => + membershipFilter == Membership.join || + member.membership == membershipFilter, + ) + .toList(); + if (filter.isEmpty) { setState(() { filteredMembers = members @@ -42,7 +60,8 @@ class ChatMembersController extends State { }); } - void refreshMembers() async { + void refreshMembers([_]) async { + Logs().d('Load room members from', widget.roomId); try { setState(() { error = null; @@ -50,7 +69,7 @@ class ChatMembersController extends State { final participants = await Matrix.of(context) .client .getRoomById(widget.roomId) - ?.requestParticipants(); + ?.requestParticipants(Membership.values); if (!mounted) return; @@ -67,10 +86,30 @@ class ChatMembersController extends State { } } + StreamSubscription? _updateSub; + @override void initState() { super.initState(); refreshMembers(); + + _updateSub = Matrix.of(context) + .client + .onSync + .stream + .where( + (syncUpdate) => + syncUpdate.rooms?.join?[widget.roomId]?.timeline?.events + ?.any((state) => state.type == EventTypes.RoomMember) ?? + false, + ) + .listen(refreshMembers); + } + + @override + void dispose() { + _updateSub?.cancel(); + super.dispose(); } @override diff --git a/lib/pages/chat_members/chat_members_view.dart b/lib/pages/chat_members/chat_members_view.dart index be53f99c7..e1598344c 100644 --- a/lib/pages/chat_members/chat_members_view.dart +++ b/lib/pages/chat_members/chat_members_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import '../../widgets/layouts/max_width_body.dart'; @@ -11,6 +12,7 @@ import 'chat_members.dart'; class ChatMembersView extends StatelessWidget { final ChatMembersController controller; + const ChatMembersView(this.controller, {super.key}); @override @@ -84,29 +86,89 @@ class ChatMembersView extends StatelessWidget { : ListView.builder( shrinkWrap: true, itemCount: members.length + 1, - itemBuilder: (context, i) => i == 0 - ? Padding( - padding: const EdgeInsets.all(16.0), - child: TextField( - controller: controller.filterController, - onChanged: controller.setFilter, - decoration: InputDecoration( - filled: true, - fillColor: theme.colorScheme.secondaryContainer, - border: OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(99), - ), - hintStyle: TextStyle( - color: theme.colorScheme.onPrimaryContainer, - fontWeight: FontWeight.normal, + itemBuilder: (context, i) { + if (i == 0) { + final availableFilters = Membership.values + .where( + (membership) => + controller.members?.any( + (member) => member.membership == membership, + ) ?? + false, + ) + .toList(); + availableFilters + .sort((a, b) => a == Membership.join ? -1 : 1); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: TextField( + controller: controller.filterController, + onChanged: controller.setFilter, + decoration: InputDecoration( + filled: true, + fillColor: + theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), + prefixIcon: const Icon(Icons.search_outlined), + hintText: L10n.of(context).search, ), - prefixIcon: const Icon(Icons.search_outlined), - hintText: L10n.of(context).search, ), ), - ) - : ParticipantListItem(members[i - 1]), + if (availableFilters.length > 1) + SizedBox( + height: 64, + child: ListView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 12.0, + ), + scrollDirection: Axis.horizontal, + itemCount: availableFilters.length, + itemBuilder: (context, i) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + ), + child: FilterChip( + label: Text( + switch (availableFilters[i]) { + Membership.ban => + L10n.of(context).banned, + Membership.invite => + L10n.of(context).invited, + Membership.join => + L10n.of(context).all, + Membership.knock => + L10n.of(context).knocking, + Membership.leave => + L10n.of(context).leftTheChat, + }, + ), + selected: controller.membershipFilter == + availableFilters[i], + onSelected: (_) => + controller.setMembershipFilter( + availableFilters[i], + ), + ), + ), + ), + ), + ], + ); + } + i--; + return ParticipantListItem(members[i]); + }, ), ), ); diff --git a/lib/widgets/member_actions_popup_menu_button.dart b/lib/widgets/member_actions_popup_menu_button.dart index c89db0d23..00c3a7989 100644 --- a/lib/widgets/member_actions_popup_menu_button.dart +++ b/lib/widgets/member_actions_popup_menu_button.dart @@ -84,6 +84,17 @@ void showMemberActionsPopupMenu({ ], ), ), + if (user.membership == Membership.knock) + PopupMenuItem( + value: _MemberActions.approve, + child: Row( + children: [ + const Icon(Icons.how_to_reg_outlined), + const SizedBox(width: 18), + Text(L10n.of(context).approve), + ], + ), + ), PopupMenuItem( enabled: user.room.canChangePowerLevel && user.canChangeUserPowerLevel, value: _MemberActions.setRole, @@ -202,9 +213,14 @@ void showMemberActionsPopupMenu({ future: () => user.setPower(power), ); return; + case _MemberActions.approve: + await showFutureLoadingDialog( + context: context, + future: () => user.room.invite(user.id), + ); + return; case _MemberActions.kick: if (await showOkCancelAlertDialog( - useRootNavigator: false, context: context, title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, @@ -220,7 +236,6 @@ void showMemberActionsPopupMenu({ return; case _MemberActions.ban: if (await showOkCancelAlertDialog( - useRootNavigator: false, context: context, title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, @@ -268,7 +283,6 @@ void showMemberActionsPopupMenu({ return; case _MemberActions.unban: if (await showOkCancelAlertDialog( - useRootNavigator: false, context: context, title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, @@ -290,6 +304,7 @@ enum _MemberActions { setRole, kick, ban, + approve, unban, report, } From c01e4ba797083998fe27ed5d8a12e67e620db19c Mon Sep 17 00:00:00 2001 From: Krille Date: Sun, 13 Apr 2025 13:34:52 +0200 Subject: [PATCH 05/20] refactor: Move public room bottom sheet into dialog Signed-off-by: Krille --- assets/l10n/intl_en.arb | 4 +- lib/pages/chat_list/chat_list_body.dart | 8 +- lib/pages/chat_list/space_view.dart | 8 +- lib/utils/url_launcher.dart | 8 +- .../adaptive_dialogs/public_room_dialog.dart | 228 ++++++++++++++++++ lib/widgets/adaptive_dialogs/user_dialog.dart | 192 ++++++++------- lib/widgets/avatar.dart | 2 +- lib/widgets/public_room_bottom_sheet.dart | 1 + 8 files changed, 336 insertions(+), 115 deletions(-) create mode 100644 lib/widgets/adaptive_dialogs/public_room_dialog.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 73ccd9a9c..63fc5131c 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3212,5 +3212,7 @@ "optionalMessage": "(Optional) message...", "notSupportedOnThisDevice": "Not supported on this device", "enterNewChat": "Enter new chat", - "approve": "Approve" + "approve": "Approve", + "youHaveKnocked": "You have knocked", + "pleaseWaitUntilInvited": "Please wait now, until someone from the room invites you." } diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index af19d17c8..7699b7ed0 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -11,10 +11,9 @@ import 'package:fluffychat/pages/chat_list/dummy_chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; import 'package:fluffychat/pages/chat_list/space_view.dart'; import 'package:fluffychat/pages/chat_list/status_msg_list.dart'; -import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/stream_extension.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/public_room_dialog.dart'; import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; import '../../config/themes.dart'; import '../../widgets/adaptive_dialogs/user_dialog.dart'; import '../../widgets/matrix.dart'; @@ -302,12 +301,11 @@ class PublicRoomsHorizontalList extends StatelessWidget { publicRooms[i].canonicalAlias?.localpart ?? L10n.of(context).group, avatar: publicRooms[i].avatarUrl, - onPressed: () => showAdaptiveBottomSheet( + onPressed: () => showAdaptiveDialog( context: context, - builder: (c) => PublicRoomBottomSheet( + builder: (c) => PublicRoomDialog( roomAlias: publicRooms[i].canonicalAlias ?? publicRooms[i].roomId, - outerContext: context, chunk: publicRooms[i], ), ), diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index b39d96a6d..510364546 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -10,16 +10,15 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; -import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/stream_extension.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/public_room_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; enum AddRoomType { chat, subspace } @@ -100,10 +99,9 @@ class _SpaceViewState extends State { final client = Matrix.of(context).client; final space = client.getRoomById(widget.spaceId); - final joined = await showAdaptiveBottomSheet( + final joined = await showAdaptiveDialog( context: context, - builder: (_) => PublicRoomBottomSheet( - outerContext: context, + builder: (_) => PublicRoomDialog( chunk: item, via: space?.spaceChildren .firstWhereOrNull( diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index 3c5469292..0077bafcd 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -8,12 +8,11 @@ import 'package:punycode/punycode.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/user_dialog.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; +import '../widgets/adaptive_dialogs/public_room_dialog.dart'; import 'platform_infos.dart'; class UrlLauncher { @@ -179,11 +178,10 @@ class UrlLauncher { } return; } else { - await showAdaptiveBottomSheet( + await showAdaptiveDialog( context: context, - builder: (c) => PublicRoomBottomSheet( + builder: (c) => PublicRoomDialog( roomAlias: identityParts.primaryIdentifier, - outerContext: context, ), ); } diff --git a/lib/widgets/adaptive_dialogs/public_room_dialog.dart b/lib/widgets/adaptive_dialogs/public_room_dialog.dart new file mode 100644 index 000000000..3e03ea5a7 --- /dev/null +++ b/lib/widgets/adaptive_dialogs/public_room_dialog.dart @@ -0,0 +1,228 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; +import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; +import '../../config/themes.dart'; +import '../../utils/url_launcher.dart'; +import '../avatar.dart'; +import '../future_loading_dialog.dart'; +import '../hover_builder.dart'; +import '../matrix.dart'; +import '../mxc_image_viewer.dart'; +import 'adaptive_dialog_action.dart'; + +class PublicRoomDialog extends StatelessWidget { + final String? roomAlias; + final PublicRoomsChunk? chunk; + final List? via; + + const PublicRoomDialog({super.key, this.roomAlias, this.chunk, this.via}); + + void _joinRoom(BuildContext context) async { + final client = Matrix.of(context).client; + final chunk = this.chunk; + final knock = chunk?.joinRule == 'knock'; + final result = await showFutureLoadingDialog( + context: context, + future: () async { + if (chunk != null && client.getRoomById(chunk.roomId) != null) { + return chunk.roomId; + } + final roomId = chunk != null && knock + ? await client.knockRoom(chunk.roomId, via: via) + : await client.joinRoom( + roomAlias ?? chunk!.roomId, + via: via, + ); + + if (!knock && client.getRoomById(roomId) == null) { + await client.waitForRoomInSync(roomId); + } + return roomId; + }, + ); + final roomId = result.result; + if (roomId == null) return; + if (knock && client.getRoomById(roomId) == null) { + Navigator.of(context).pop(true); + await showOkAlertDialog( + context: context, + title: L10n.of(context).youHaveKnocked, + message: L10n.of(context).pleaseWaitUntilInvited, + ); + return; + } + if (result.error != null) return; + if (!context.mounted) return; + Navigator.of(context).pop(true); + // don't open the room if the joined room is a space + if (chunk?.roomType != 'm.space' && + !client.getRoomById(result.result!)!.isSpace) { + context.go('/rooms/$roomId'); + } + return; + } + + bool _testRoom(PublicRoomsChunk r) => r.canonicalAlias == roomAlias; + + Future _search(BuildContext context) async { + final chunk = this.chunk; + if (chunk != null) return chunk; + final query = await Matrix.of(context).client.queryPublicRooms( + server: roomAlias!.domain, + filter: PublicRoomQueryFilter( + genericSearchTerm: roomAlias, + ), + ); + if (!query.chunk.any(_testRoom)) { + throw (L10n.of(context).noRoomsFound); + } + return query.chunk.firstWhere(_testRoom); + } + + @override + Widget build(BuildContext context) { + final roomAlias = this.roomAlias ?? chunk?.canonicalAlias; + final roomLink = roomAlias ?? chunk?.roomId; + var copied = false; + return AlertDialog.adaptive( + title: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256), + child: Text( + chunk?.name ?? roomAlias ?? chunk?.roomId ?? 'Unknown', + overflow: TextOverflow.fade, + ), + ), + content: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), + child: FutureBuilder( + future: _search(context), + builder: (context, snapshot) { + final theme = Theme.of(context); + + final profile = snapshot.data; + final avatar = profile?.avatarUrl; + final topic = profile?.topic; + return SingleChildScrollView( + child: Column( + spacing: 8, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (roomLink != null) + HoverBuilder( + builder: (context, hovered) => StatefulBuilder( + builder: (context, setState) => MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + Clipboard.setData( + ClipboardData(text: roomLink), + ); + setState(() { + copied = true; + }); + }, + child: RichText( + text: TextSpan( + children: [ + WidgetSpan( + child: Padding( + padding: + const EdgeInsets.only(right: 4.0), + child: AnimatedScale( + duration: + FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: hovered + ? 1.33 + : copied + ? 1.25 + : 1.0, + child: Icon( + copied + ? Icons.check_circle + : Icons.copy, + size: 12, + color: copied ? Colors.green : null, + ), + ), + ), + ), + TextSpan(text: roomLink), + ], + style: theme.textTheme.bodyMedium + ?.copyWith(fontSize: 10), + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + ), + Center( + child: Avatar( + mxContent: avatar, + name: profile?.name ?? roomLink, + size: Avatar.defaultSize * 2, + onTap: avatar != null + ? () => showDialog( + context: context, + builder: (_) => MxcImageViewer(avatar), + ) + : null, + ), + ), + Text( + L10n.of(context).countParticipants( + profile?.numJoinedMembers ?? 0, + ), + style: const TextStyle(fontSize: 10), + textAlign: TextAlign.center, + ), + if (topic != null && topic.isNotEmpty) + SelectableLinkify( + text: topic, + textAlign: TextAlign.center, + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: theme.colorScheme.primary, + decoration: TextDecoration.underline, + decorationColor: theme.colorScheme.primary, + ), + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), + ), + ], + ), + ); + }, + ), + ), + actions: [ + AdaptiveDialogAction( + bigButtons: true, + onPressed: () => _joinRoom(context), + child: Text( + 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, + ), + ), + AdaptiveDialogAction( + bigButtons: true, + onPressed: Navigator.of(context).pop, + child: Text(L10n.of(context).close), + ), + ], + ); + } +} diff --git a/lib/widgets/adaptive_dialogs/user_dialog.dart b/lib/widgets/adaptive_dialogs/user_dialog.dart index 34fe1739f..3c7281fb9 100644 --- a/lib/widgets/adaptive_dialogs/user_dialog.dart +++ b/lib/widgets/adaptive_dialogs/user_dialog.dart @@ -54,114 +54,110 @@ class UserDialog extends StatelessWidget { ), content: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), - child: SelectionArea( - child: PresenceBuilder( - userId: profile.userId, - client: Matrix.of(context).client, - builder: (context, presence) { - if (presence == null) return const SizedBox.shrink(); - final statusMsg = presence.statusMsg; - final lastActiveTimestamp = presence.lastActiveTimestamp; - final presenceText = presence.currentlyActive == true - ? L10n.of(context).currentlyActive - : lastActiveTimestamp != null - ? L10n.of(context).lastActiveAgo( - lastActiveTimestamp.localizedTimeShort(context), - ) - : null; - return SingleChildScrollView( - child: Column( - spacing: 8, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - HoverBuilder( - builder: (context, hovered) => StatefulBuilder( - builder: (context, setState) => MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - Clipboard.setData( - ClipboardData(text: profile.userId), - ); - setState(() { - copied = true; - }); - }, - child: RichText( - text: TextSpan( - children: [ - WidgetSpan( - child: Padding( - padding: - const EdgeInsets.only(right: 4.0), - child: AnimatedScale( - duration: - FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - scale: hovered - ? 1.33 - : copied - ? 1.25 - : 1.0, - child: Icon( - copied - ? Icons.check_circle - : Icons.copy, - size: 12, - color: copied ? Colors.green : null, - ), + child: PresenceBuilder( + userId: profile.userId, + client: Matrix.of(context).client, + builder: (context, presence) { + if (presence == null) return const SizedBox.shrink(); + final statusMsg = presence.statusMsg; + final lastActiveTimestamp = presence.lastActiveTimestamp; + final presenceText = presence.currentlyActive == true + ? L10n.of(context).currentlyActive + : lastActiveTimestamp != null + ? L10n.of(context).lastActiveAgo( + lastActiveTimestamp.localizedTimeShort(context), + ) + : null; + return SingleChildScrollView( + child: Column( + spacing: 8, + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + HoverBuilder( + builder: (context, hovered) => StatefulBuilder( + builder: (context, setState) => MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + Clipboard.setData( + ClipboardData(text: profile.userId), + ); + setState(() { + copied = true; + }); + }, + child: RichText( + text: TextSpan( + children: [ + WidgetSpan( + child: Padding( + padding: const EdgeInsets.only(right: 4.0), + child: AnimatedScale( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: hovered + ? 1.33 + : copied + ? 1.25 + : 1.0, + child: Icon( + copied + ? Icons.check_circle + : Icons.copy, + size: 12, + color: copied ? Colors.green : null, ), ), ), - TextSpan(text: profile.userId), - ], - style: theme.textTheme.bodyMedium - ?.copyWith(fontSize: 10), - ), - textAlign: TextAlign.center, + ), + TextSpan(text: profile.userId), + ], + style: theme.textTheme.bodyMedium + ?.copyWith(fontSize: 10), ), + textAlign: TextAlign.center, ), ), ), ), - Center( - child: Avatar( - mxContent: avatar, - name: displayname, - size: Avatar.defaultSize * 2, - onTap: avatar != null - ? () => showDialog( - context: context, - builder: (_) => MxcImageViewer(avatar), - ) - : null, - ), + ), + Center( + child: Avatar( + mxContent: avatar, + name: displayname, + size: Avatar.defaultSize * 2, + onTap: avatar != null + ? () => showDialog( + context: context, + builder: (_) => MxcImageViewer(avatar), + ) + : null, ), - if (presenceText != null) - Text( - presenceText, - style: const TextStyle(fontSize: 10), - textAlign: TextAlign.center, - ), - if (statusMsg != null) - Linkify( - text: statusMsg, - textAlign: TextAlign.center, - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: theme.colorScheme.primary, - decoration: TextDecoration.underline, - decorationColor: theme.colorScheme.primary, - ), - onOpen: (url) => - UrlLauncher(context, url.url).launchUrl(), + ), + if (presenceText != null) + Text( + presenceText, + style: const TextStyle(fontSize: 10), + textAlign: TextAlign.center, + ), + if (statusMsg != null) + SelectableLinkify( + text: statusMsg, + textAlign: TextAlign.center, + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: theme.colorScheme.primary, + decoration: TextDecoration.underline, + decorationColor: theme.colorScheme.primary, ), - ], - ), - ); - }, - ), + onOpen: (url) => + UrlLauncher(context, url.url).launchUrl(), + ), + ], + ), + ); + }, ), ), actions: [ diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 0a60c1b4a..25952bd71 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -62,7 +62,7 @@ class Avatar extends StatelessWidget { clipBehavior: Clip.hardEdge, child: noPic ? Container( - decoration: BoxDecoration(color: name!.lightColorAvatar), + decoration: BoxDecoration(color: name?.lightColorAvatar), alignment: Alignment.center, child: Text( fallbackLetters, diff --git a/lib/widgets/public_room_bottom_sheet.dart b/lib/widgets/public_room_bottom_sheet.dart index a2ca96b7f..01f1d69d2 100644 --- a/lib/widgets/public_room_bottom_sheet.dart +++ b/lib/widgets/public_room_bottom_sheet.dart @@ -12,6 +12,7 @@ import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/qr_code_viewer.dart'; +@Deprecated('') class PublicRoomBottomSheet extends StatelessWidget { final String? roomAlias; final BuildContext outerContext; From a1223c0e9be7c3a3f8a7cb3567812577eb9992d8 Mon Sep 17 00:00:00 2001 From: Krille Date: Mon, 14 Apr 2025 10:59:53 +0200 Subject: [PATCH 06/20] chore: Follow up public rooms dialog Signed-off-by: Krille --- .../adaptive_dialogs/public_room_dialog.dart | 20 +- lib/widgets/public_room_bottom_sheet.dart | 234 ------------------ 2 files changed, 10 insertions(+), 244 deletions(-) delete mode 100644 lib/widgets/public_room_bottom_sheet.dart diff --git a/lib/widgets/adaptive_dialogs/public_room_dialog.dart b/lib/widgets/adaptive_dialogs/public_room_dialog.dart index 3e03ea5a7..ded3fb077 100644 --- a/lib/widgets/adaptive_dialogs/public_room_dialog.dart +++ b/lib/widgets/adaptive_dialogs/public_room_dialog.dart @@ -1,12 +1,11 @@ +import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import '../../config/themes.dart'; import '../../utils/url_launcher.dart'; import '../avatar.dart'; @@ -94,8 +93,8 @@ class PublicRoomDialog extends StatelessWidget { title: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256), child: Text( - chunk?.name ?? roomAlias ?? chunk?.roomId ?? 'Unknown', - overflow: TextOverflow.fade, + chunk?.name ?? roomAlias?.localpart ?? chunk?.roomId ?? 'Unknown', + textAlign: TextAlign.center, ), ), content: ConstrainedBox( @@ -178,13 +177,14 @@ class PublicRoomDialog extends StatelessWidget { : null, ), ), - Text( - L10n.of(context).countParticipants( - profile?.numJoinedMembers ?? 0, + if (profile?.numJoinedMembers != null) + Text( + L10n.of(context).countParticipants( + profile?.numJoinedMembers ?? 0, + ), + style: const TextStyle(fontSize: 10), + textAlign: TextAlign.center, ), - style: const TextStyle(fontSize: 10), - textAlign: TextAlign.center, - ), if (topic != null && topic.isNotEmpty) SelectableLinkify( text: topic, diff --git a/lib/widgets/public_room_bottom_sheet.dart b/lib/widgets/public_room_bottom_sheet.dart deleted file mode 100644 index 01f1d69d2..000000000 --- a/lib/widgets/public_room_bottom_sheet.dart +++ /dev/null @@ -1,234 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_linkify/flutter_linkify.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/utils/fluffy_share.dart'; -import 'package:fluffychat/utils/url_launcher.dart'; -import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:fluffychat/widgets/qr_code_viewer.dart'; - -@Deprecated('') -class PublicRoomBottomSheet extends StatelessWidget { - final String? roomAlias; - final BuildContext outerContext; - final PublicRoomsChunk? chunk; - final List? via; - - PublicRoomBottomSheet({ - this.roomAlias, - required this.outerContext, - this.chunk, - this.via, - super.key, - }) { - assert(roomAlias != null || chunk != null); - } - - void _joinRoom(BuildContext context) async { - final client = Matrix.of(outerContext).client; - final chunk = this.chunk; - final knock = chunk?.joinRule == 'knock'; - final result = await showFutureLoadingDialog( - context: context, - future: () async { - if (chunk != null && client.getRoomById(chunk.roomId) != null) { - return chunk.roomId; - } - final roomId = chunk != null && knock - ? await client.knockRoom(chunk.roomId, via: via) - : await client.joinRoom( - roomAlias ?? chunk!.roomId, - via: via, - ); - - if (!knock && client.getRoomById(roomId) == null) { - await client.waitForRoomInSync(roomId); - } - return roomId; - }, - ); - if (knock) { - return; - } - if (result.error == null) { - Navigator.of(context).pop(true); - // don't open the room if the joined room is a space - if (chunk?.roomType != 'm.space' && - !client.getRoomById(result.result!)!.isSpace) { - outerContext.go('/rooms/${result.result!}'); - } - return; - } - } - - bool _testRoom(PublicRoomsChunk r) => r.canonicalAlias == roomAlias; - - Future _search() async { - final chunk = this.chunk; - if (chunk != null) return chunk; - final query = await Matrix.of(outerContext).client.queryPublicRooms( - server: roomAlias!.domain, - filter: PublicRoomQueryFilter( - genericSearchTerm: roomAlias, - ), - ); - if (!query.chunk.any(_testRoom)) { - throw (L10n.of(outerContext).noRoomsFound); - } - return query.chunk.firstWhere(_testRoom); - } - - @override - Widget build(BuildContext context) { - final roomAlias = this.roomAlias ?? chunk?.canonicalAlias; - final roomLink = roomAlias ?? chunk?.roomId; - return SafeArea( - child: Scaffold( - appBar: AppBar( - title: Text( - chunk?.name ?? roomAlias ?? chunk?.roomId ?? 'Unknown', - overflow: TextOverflow.fade, - ), - leading: Center( - child: CloseButton( - onPressed: Navigator.of(context, rootNavigator: false).pop, - ), - ), - actions: roomAlias == null - ? null - : [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: IconButton( - icon: const Icon(Icons.qr_code_rounded), - onPressed: () => showQrCodeViewer( - context, - roomAlias, - ), - ), - ), - ], - ), - body: FutureBuilder( - future: _search(), - builder: (context, snapshot) { - final theme = Theme.of(context); - - final profile = snapshot.data; - return ListView( - padding: EdgeInsets.zero, - children: [ - Row( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: profile == null - ? const Center( - child: CircularProgressIndicator.adaptive(), - ) - : Avatar( - client: Matrix.of(outerContext).client, - mxContent: profile.avatarUrl, - name: profile.name ?? roomAlias, - size: Avatar.defaultSize * 3, - ), - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextButton.icon( - onPressed: roomLink != null - ? () => FluffyShare.share( - roomLink, - context, - copyOnly: true, - ) - : null, - icon: const Icon( - Icons.copy_outlined, - size: 14, - ), - style: TextButton.styleFrom( - foregroundColor: theme.colorScheme.onSurface, - iconColor: theme.colorScheme.onSurface, - ), - label: Text( - roomLink ?? '...', - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - TextButton.icon( - onPressed: () {}, - icon: const Icon( - Icons.groups_3_outlined, - size: 14, - ), - style: TextButton.styleFrom( - foregroundColor: theme.colorScheme.onSurface, - iconColor: theme.colorScheme.onSurface, - ), - label: Text( - L10n.of(context).countParticipants( - profile?.numJoinedMembers ?? 0, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: ElevatedButton.icon( - onPressed: () => _joinRoom(context), - label: Text( - chunk?.joinRule == 'knock' && - Matrix.of(outerContext) - .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.navigate_next), - ), - ), - const SizedBox(height: 16), - if (profile?.topic?.isNotEmpty ?? false) - ListTile( - subtitle: SelectableLinkify( - text: profile!.topic!, - linkStyle: TextStyle( - color: theme.colorScheme.primary, - decorationColor: theme.colorScheme.primary, - ), - style: TextStyle( - fontSize: 14, - color: theme.textTheme.bodyMedium!.color, - ), - options: const LinkifyOptions(humanize: false), - onOpen: (url) => - UrlLauncher(context, url.url).launchUrl(), - ), - ), - ], - ); - }, - ), - ), - ); - } -} From 60fe90233b8590c3c614fbe2e48e0193e67c03cf Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 14:44:51 +0200 Subject: [PATCH 07/20] fix: Text scale factor in Linkify widgets Signed-off-by: Krille --- lib/pages/chat/chat_app_bar_list_tile.dart | 1 + lib/pages/chat/events/audio_player.dart | 2 ++ lib/pages/chat/events/image_bubble.dart | 1 + lib/pages/chat/events/message_content.dart | 1 + .../chat/events/message_download_content.dart | 1 + lib/pages/chat/events/video_player.dart | 2 ++ lib/pages/chat_details/chat_details_view.dart | 2 ++ .../chat_search/chat_search_message_tab.dart | 1 + .../homeserver_picker/homeserver_picker_view.dart | 15 +++++++++++++++ .../settings_homeserver_view.dart | 6 ++++++ .../adaptive_dialogs/public_room_dialog.dart | 5 ++++- .../show_ok_cancel_alert_dialog.dart | 2 ++ .../adaptive_dialogs/show_text_input_dialog.dart | 1 + lib/widgets/adaptive_dialogs/user_dialog.dart | 2 ++ 14 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat/chat_app_bar_list_tile.dart b/lib/pages/chat/chat_app_bar_list_tile.dart index 1ca0c5fba..a1fc21b43 100644 --- a/lib/pages/chat/chat_app_bar_list_tile.dart +++ b/lib/pages/chat/chat_app_bar_list_tile.dart @@ -37,6 +37,7 @@ class ChatAppBarListTile extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 4.0), child: Linkify( text: title, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), maxLines: 1, overflow: TextOverflow.ellipsis, diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 8efcc190a..41e1f8606 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -397,6 +397,7 @@ class AudioPlayerState extends State { const SizedBox(height: 8), Linkify( text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: widget.color, fontSize: widget.fontSize, @@ -420,6 +421,7 @@ class AudioPlayerState extends State { /// To use a MatrixFile as an AudioSource for the just_audio package class MatrixFileAudioSource extends StreamAudioSource { final MatrixFile file; + MatrixFileAudioSource(this.file); @override diff --git a/lib/pages/chat/events/image_bubble.dart b/lib/pages/chat/events/image_bubble.dart index 3fa352d25..4a77af18f 100644 --- a/lib/pages/chat/events/image_bubble.dart +++ b/lib/pages/chat/events/image_bubble.dart @@ -124,6 +124,7 @@ class ImageBubble extends StatelessWidget { width: width, child: Linkify( text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 40e237abd..2df156bbc 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -281,6 +281,7 @@ class MessageContent extends StatelessWidget { MatrixLocals(L10n.of(context)), hideReply: true, ), + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, fontSize: bigEmotes ? fontSize * 5 : fontSize, diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index b759895ef..31a5c0708 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -94,6 +94,7 @@ class MessageDownloadContent extends StatelessWidget { if (fileDescription != null) Linkify( text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 5cb5cf913..13f860609 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -25,6 +25,7 @@ class EventVideoPlayer extends StatefulWidget { final Event event; final Color? textColor; final Color? linkColor; + const EventVideoPlayer( this.event, { this.textColor, @@ -190,6 +191,7 @@ class EventVideoPlayerState extends State { width: width, child: Linkify( text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index e96c10d82..a5c724e7a 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -243,6 +243,8 @@ class ChatDetailsView extends StatelessWidget { text: room.topic.isEmpty ? L10n.of(context).noChatDescriptionYet : room.topic, + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: const TextStyle( color: Colors.blueAccent, diff --git a/lib/pages/chat_search/chat_search_message_tab.dart b/lib/pages/chat_search/chat_search_message_tab.dart index 7c7024e8d..18d6de4a0 100644 --- a/lib/pages/chat_search/chat_search_message_tab.dart +++ b/lib/pages/chat_search/chat_search_message_tab.dart @@ -152,6 +152,7 @@ class _MessageSearchResultListTile extends StatelessWidget { ], ), subtitle: Linkify( + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, diff --git a/lib/pages/homeserver_picker/homeserver_picker_view.dart b/lib/pages/homeserver_picker/homeserver_picker_view.dart index e4782b35f..df3b69489 100644 --- a/lib/pages/homeserver_picker/homeserver_picker_view.dart +++ b/lib/pages/homeserver_picker/homeserver_picker_view.dart @@ -122,6 +122,8 @@ class HomeserverPickerView extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 32.0), child: SelectableLinkify( text: L10n.of(context).appIntroduction, + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), textAlign: TextAlign.center, linkStyle: TextStyle( color: theme.colorScheme.secondary, @@ -169,6 +171,19 @@ class HomeserverPickerView extends StatelessWidget { content: Linkify( text: L10n.of(context) .homeserverDescription, + textScaleFactor: + MediaQuery.textScalerOf(context) + .scale(1), + options: const LinkifyOptions( + humanize: false, + ), + linkStyle: TextStyle( + color: theme.colorScheme.primary, + decorationColor: + theme.colorScheme.primary, + ), + onOpen: (link) => + launchUrlString(link.url), ), actions: [ AdaptiveDialogAction( diff --git a/lib/pages/settings_homeserver/settings_homeserver_view.dart b/lib/pages/settings_homeserver/settings_homeserver_view.dart index 6de7102e8..c75f88508 100644 --- a/lib/pages/settings_homeserver/settings_homeserver_view.dart +++ b/lib/pages/settings_homeserver/settings_homeserver_view.dart @@ -169,6 +169,8 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Federation Base URL'), subtitle: Linkify( text: data.federationBaseUrl.toString(), + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, @@ -231,6 +233,8 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Base URL'), subtitle: Linkify( text: wellKnown.mHomeserver.baseUrl.toString(), + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, @@ -244,6 +248,8 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Identity Server:'), subtitle: Linkify( text: identityServer.baseUrl.toString(), + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, diff --git a/lib/widgets/adaptive_dialogs/public_room_dialog.dart b/lib/widgets/adaptive_dialogs/public_room_dialog.dart index ded3fb077..4f0070ffd 100644 --- a/lib/widgets/adaptive_dialogs/public_room_dialog.dart +++ b/lib/widgets/adaptive_dialogs/public_room_dialog.dart @@ -1,11 +1,12 @@ -import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; + import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import '../../config/themes.dart'; import '../../utils/url_launcher.dart'; import '../avatar.dart'; @@ -188,6 +189,8 @@ class PublicRoomDialog extends StatelessWidget { if (topic != null && topic.isNotEmpty) SelectableLinkify( text: topic, + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), textAlign: TextAlign.center, options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( diff --git a/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart b/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart index 8c2f861e4..585524d2c 100644 --- a/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart +++ b/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart @@ -31,6 +31,7 @@ Future showOkCancelAlertDialog({ ? null : SelectableLinkify( text: message, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), linkStyle: TextStyle( color: Theme.of(context).colorScheme.primary, decorationColor: Theme.of(context).colorScheme.primary, @@ -81,6 +82,7 @@ Future showOkAlertDialog({ ? null : SelectableLinkify( text: message, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), linkStyle: TextStyle( color: Theme.of(context).colorScheme.primary, decorationColor: Theme.of(context).colorScheme.primary, diff --git a/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart b/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart index 4ad5ea3f0..bbfe28a18 100644 --- a/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart +++ b/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart @@ -49,6 +49,7 @@ Future showTextInputDialog({ if (message != null) SelectableLinkify( text: message, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), linkStyle: TextStyle( color: Theme.of(context).colorScheme.primary, decorationColor: Theme.of(context).colorScheme.primary, diff --git a/lib/widgets/adaptive_dialogs/user_dialog.dart b/lib/widgets/adaptive_dialogs/user_dialog.dart index 3c7281fb9..bc6881ac6 100644 --- a/lib/widgets/adaptive_dialogs/user_dialog.dart +++ b/lib/widgets/adaptive_dialogs/user_dialog.dart @@ -144,6 +144,8 @@ class UserDialog extends StatelessWidget { if (statusMsg != null) SelectableLinkify( text: statusMsg, + textScaleFactor: + MediaQuery.textScalerOf(context).scale(1), textAlign: TextAlign.center, options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( From 50a22f89437abea0bb5e18cbe7a5f17605a4ff76 Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 15:05:38 +0200 Subject: [PATCH 08/20] chore: Add matrix notifications for issues Signed-off-by: Krille --- .github/workflows/matrix_notification.yaml | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/matrix_notification.yaml diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml new file mode 100644 index 000000000..106cb781c --- /dev/null +++ b/.github/workflows/matrix_notification.yaml @@ -0,0 +1,27 @@ +name: Matrix Notification + +on: + issues: + types: [ opened ] + issue_comment: + types: [ created ] + +jobs: + notify: + runs-on: ubuntu-latest + + steps: + - name: Send Matrix Notification + env: + MATRIX_URL: https://matrix.org/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message + MATRIX_ACCESS_TOKEN: ${{ secrets.MATRIX_BOT_TOKEN + run: | + if [ "${{ github.event_name }}" == "issues" ]; then + PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" + else + PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" + fi + curl -XPOST -H "Authorization: Bearer $MATRIX_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" \ + $MATRIX_URL From c708cc8c9bec6a177c346dd34c1d604e17f68b40 Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 15:09:34 +0200 Subject: [PATCH 09/20] chore: Follow up matrix notification Signed-off-by: Krille --- .github/workflows/matrix_notification.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml index 106cb781c..730272e81 100644 --- a/.github/workflows/matrix_notification.yaml +++ b/.github/workflows/matrix_notification.yaml @@ -14,11 +14,11 @@ jobs: - name: Send Matrix Notification env: MATRIX_URL: https://matrix.org/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message - MATRIX_ACCESS_TOKEN: ${{ secrets.MATRIX_BOT_TOKEN + MATRIX_ACCESS_TOKEN: ${{ secrets.MATRIX_BOT_TOKEN }} run: | - if [ "${{ github.event_name }}" == "issues" ]; then + if [ "${{ github.event.action }}" == "opened" ]; then PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" - else + elif [ "${{ github.event.action }}" == "created" ]; then PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" fi curl -XPOST -H "Authorization: Bearer $MATRIX_ACCESS_TOKEN" \ From 8a2b9933b3dac0660cb89e85b7be37c1706a073d Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 15:12:51 +0200 Subject: [PATCH 10/20] chore: Follow up matrix notification Signed-off-by: Krille --- .github/workflows/matrix_notification.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml index 730272e81..4778e7739 100644 --- a/.github/workflows/matrix_notification.yaml +++ b/.github/workflows/matrix_notification.yaml @@ -14,14 +14,13 @@ jobs: - name: Send Matrix Notification env: MATRIX_URL: https://matrix.org/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message - MATRIX_ACCESS_TOKEN: ${{ secrets.MATRIX_BOT_TOKEN }} run: | if [ "${{ github.event.action }}" == "opened" ]; then PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" elif [ "${{ github.event.action }}" == "created" ]; then PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" fi - curl -XPOST -H "Authorization: Bearer $MATRIX_ACCESS_TOKEN" \ + curl -XPOST -H "Authorization: Bearer ${{ secrets.MATRIX_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ $MATRIX_URL From ce9a0f0e4f9aff2b4cf0118c1f14a10321b0063a Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 15:18:29 +0200 Subject: [PATCH 11/20] chore: Follow up matrix notification Signed-off-by: Krille --- .github/workflows/matrix_notification.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml index 4778e7739..f1ced54f1 100644 --- a/.github/workflows/matrix_notification.yaml +++ b/.github/workflows/matrix_notification.yaml @@ -13,14 +13,14 @@ jobs: steps: - name: Send Matrix Notification env: - MATRIX_URL: https://matrix.org/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message + MATRIX_URL: https://matrix.janian.de/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message run: | if [ "${{ github.event.action }}" == "opened" ]; then - PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" + PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" elif [ "${{ github.event.action }}" == "created" ]; then - PAYLOAD="{\"msgtype\": \"m.text\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" + PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" fi - curl -XPOST -H "Authorization: Bearer ${{ secrets.MATRIX_BOT_TOKEN }}" \ + curl -X POST -H "Authorization: Bearer ${{ secrets.MATRIX_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ $MATRIX_URL From 4e91a3e34708bb0da975b16e456cfe6ddfb742ea Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 15 Apr 2025 15:20:05 +0200 Subject: [PATCH 12/20] chore: Follow up matrix notification Signed-off-by: Krille --- .github/workflows/matrix_notification.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/matrix_notification.yaml b/.github/workflows/matrix_notification.yaml index f1ced54f1..dde670df8 100644 --- a/.github/workflows/matrix_notification.yaml +++ b/.github/workflows/matrix_notification.yaml @@ -16,9 +16,9 @@ jobs: MATRIX_URL: https://matrix.janian.de/_matrix/client/v3/rooms/${{ secrets.MATRIX_MANAGEMENT_ROOM }}/send/m.room.message run: | if [ "${{ github.event.action }}" == "opened" ]; then - PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Issue Created: ${{ github.event.issue.title }}\\nCreated by: ${{ github.event.issue.user.login }}\\n${{ github.event.issue.body }}\\nURL: ${{ github.event.issue.html_url }}\"}" + PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Issue from ${{ github.event.issue.user.login }}\\n${{ github.event.issue.title }}\\n\\n${{ github.event.issue.body }}\\n\\nURL: ${{ github.event.issue.html_url }}\"}" elif [ "${{ github.event.action }}" == "created" ]; then - PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n${{ github.event.comment.body }}\\nURL: ${{ github.event.comment.html_url }}\"}" + PAYLOAD="{\"msgtype\": \"m.notice\", \"body\": \"New Comment from ${{ github.event.comment.user.login }}\\n\\n${{ github.event.comment.body }}\\n\\nURL: ${{ github.event.comment.html_url }}\"}" fi curl -X POST -H "Authorization: Bearer ${{ secrets.MATRIX_BOT_TOKEN }}" \ -H "Content-Type: application/json" \ From 955ceec288c9c0693558232d5d8798ae3bb3345c Mon Sep 17 00:00:00 2001 From: Krille Date: Thu, 17 Apr 2025 07:44:38 +0200 Subject: [PATCH 13/20] build: Flutter 3.29.3 Signed-off-by: Krille --- .github/workflows/versions.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/versions.env b/.github/workflows/versions.env index 0ec87bb48..893fcdf8d 100644 --- a/.github/workflows/versions.env +++ b/.github/workflows/versions.env @@ -1,2 +1,2 @@ -FLUTTER_VERSION=3.29.2 +FLUTTER_VERSION=3.29.3 JAVA_VERSION=17 From 64ba93d8ea6841d58288a06354295f8f0693cb8b Mon Sep 17 00:00:00 2001 From: Krille Date: Thu, 17 Apr 2025 08:14:59 +0200 Subject: [PATCH 14/20] chore: Nicer scaffold dialog for column mode Signed-off-by: Krille --- lib/pages/chat/event_info_dialog.dart | 5 ++- lib/utils/adaptive_bottom_sheet.dart | 45 +++++++++++++++++++-------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/pages/chat/event_info_dialog.dart b/lib/pages/chat/event_info_dialog.dart index dca325dfd..44443f594 100644 --- a/lib/pages/chat/event_info_dialog.dart +++ b/lib/pages/chat/event_info_dialog.dart @@ -21,6 +21,7 @@ extension EventInfoDialogExtension on Event { class EventInfoDialog extends StatelessWidget { final Event event; final L10n l10n; + const EventInfoDialog({ required this.event, required this.l10n, @@ -41,10 +42,8 @@ class EventInfoDialog extends StatelessWidget { return Scaffold( appBar: AppBar( title: Text(L10n.of(context).messageInfo), - leading: IconButton( - icon: const Icon(Icons.arrow_downward_outlined), + leading: CloseButton( onPressed: Navigator.of(context, rootNavigator: false).pop, - tooltip: L10n.of(context).close, ), ), body: ListView( diff --git a/lib/utils/adaptive_bottom_sheet.dart b/lib/utils/adaptive_bottom_sheet.dart index f2addb838..96cbe5e1e 100644 --- a/lib/utils/adaptive_bottom_sheet.dart +++ b/lib/utils/adaptive_bottom_sheet.dart @@ -12,21 +12,40 @@ Future showAdaptiveBottomSheet({ bool isScrollControlled = true, bool useRootNavigator = true, }) { - final maxHeight = min(MediaQuery.of(context).size.height - 32, 600); - final dialogMode = FluffyThemes.isColumnMode(context); - return showModalBottomSheet( + if (FluffyThemes.isColumnMode(context)) { + return showDialog( + context: context, + useRootNavigator: useRootNavigator, + barrierDismissible: isDismissible, + useSafeArea: true, + builder: (context) => Container( + margin: const EdgeInsets.all(16), + constraints: const BoxConstraints( + maxWidth: 480, + maxHeight: 720, + ), + alignment: Alignment.center, + child: Material( + elevation: Theme.of(context).dialogTheme.elevation ?? 4, + shadowColor: Theme.of(context).dialogTheme.shadowColor, + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + color: Theme.of(context).scaffoldBackgroundColor, + clipBehavior: Clip.hardEdge, + child: builder(context), + ), + ), + ); + } + + return showModalBottomSheet( context: context, builder: (context) => Padding( - padding: dialogMode - ? const EdgeInsets.symmetric(vertical: 32.0) - : EdgeInsets.zero, + padding: EdgeInsets.zero, child: ClipRRect( - borderRadius: dialogMode - ? BorderRadius.circular(AppConfig.borderRadius) - : const BorderRadius.only( - topLeft: Radius.circular(AppConfig.borderRadius), - topRight: Radius.circular(AppConfig.borderRadius), - ), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(AppConfig.borderRadius / 2), + topRight: Radius.circular(AppConfig.borderRadius / 2), + ), child: builder(context), ), ), @@ -34,7 +53,7 @@ Future showAdaptiveBottomSheet({ isDismissible: isDismissible, isScrollControlled: isScrollControlled, constraints: BoxConstraints( - maxHeight: maxHeight + (dialogMode ? 64 : 0), + maxHeight: min(MediaQuery.of(context).size.height - 32, 600), maxWidth: FluffyThemes.columnWidth * 1.25, ), backgroundColor: Colors.transparent, From 6edfb40207d5a48a1491a7cc54cf0f65bad5db45 Mon Sep 17 00:00:00 2001 From: Krille Date: Thu, 17 Apr 2025 11:10:54 +0200 Subject: [PATCH 15/20] chore: Follow up scaffold dialog Signed-off-by: Krille --- lib/utils/adaptive_bottom_sheet.dart | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/utils/adaptive_bottom_sheet.dart b/lib/utils/adaptive_bottom_sheet.dart index 96cbe5e1e..cad4d525c 100644 --- a/lib/utils/adaptive_bottom_sheet.dart +++ b/lib/utils/adaptive_bottom_sheet.dart @@ -1,9 +1,8 @@ import 'dart:math'; -import 'package:flutter/material.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; +import 'package:flutter/material.dart'; Future showAdaptiveBottomSheet({ required BuildContext context, @@ -18,20 +17,21 @@ Future showAdaptiveBottomSheet({ useRootNavigator: useRootNavigator, barrierDismissible: isDismissible, useSafeArea: true, - builder: (context) => Container( - margin: const EdgeInsets.all(16), - constraints: const BoxConstraints( - maxWidth: 480, - maxHeight: 720, - ), - alignment: Alignment.center, - child: Material( - elevation: Theme.of(context).dialogTheme.elevation ?? 4, - shadowColor: Theme.of(context).dialogTheme.shadowColor, - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - color: Theme.of(context).scaffoldBackgroundColor, - clipBehavior: Clip.hardEdge, - child: builder(context), + builder: (context) => Center( + child: Container( + margin: const EdgeInsets.all(16), + constraints: const BoxConstraints( + maxWidth: 480, + maxHeight: 720, + ), + child: Material( + elevation: Theme.of(context).dialogTheme.elevation ?? 4, + shadowColor: Theme.of(context).dialogTheme.shadowColor, + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + color: Theme.of(context).scaffoldBackgroundColor, + clipBehavior: Clip.hardEdge, + child: builder(context), + ), ), ), ); From a8a15e900beb45158c959ee8ab22f70236941c96 Mon Sep 17 00:00:00 2001 From: krille-chan Date: Fri, 18 Apr 2025 19:06:58 +0200 Subject: [PATCH 16/20] chore: Follow up members list --- lib/pages/chat_members/chat_members.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat_members/chat_members.dart b/lib/pages/chat_members/chat_members.dart index d1ab81a5a..4ca99ef31 100644 --- a/lib/pages/chat_members/chat_members.dart +++ b/lib/pages/chat_members/chat_members.dart @@ -69,7 +69,8 @@ class ChatMembersController extends State { final participants = await Matrix.of(context) .client .getRoomById(widget.roomId) - ?.requestParticipants(Membership.values); + ?.requestParticipants( + [...Membership.values]..remove(Membership.leave)); if (!mounted) return; From 8c75e31612448275fceaa62a1972ea244f178e73 Mon Sep 17 00:00:00 2001 From: krille-chan Date: Fri, 18 Apr 2025 19:35:30 +0200 Subject: [PATCH 17/20] chore: Follow up message design --- lib/pages/chat/events/audio_player.dart | 32 +++-- lib/pages/chat/events/image_bubble.dart | 43 ++++--- lib/pages/chat/events/message.dart | 10 -- lib/pages/chat/events/message_content.dart | 88 ++++++++----- .../chat/events/message_download_content.dart | 116 +++++++----------- lib/pages/chat/events/video_player.dart | 34 +++-- lib/pages/chat_members/chat_members.dart | 3 +- lib/utils/adaptive_bottom_sheet.dart | 3 +- pubspec.lock | 94 +++++++------- windows/flutter/generated_plugins.cmake | 50 ++++---- 10 files changed, 240 insertions(+), 233 deletions(-) diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 41e1f8606..10d13362d 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -395,21 +395,27 @@ class AudioPlayerState extends State { ), if (fileDescription != null) ...[ const SizedBox(height: 8), - Linkify( - text: fileDescription, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - style: TextStyle( - color: widget.color, - fontSize: widget.fontSize, + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, ), - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: widget.linkColor, - fontSize: widget.fontSize, - decoration: TextDecoration.underline, - decorationColor: widget.linkColor, + child: Linkify( + text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + style: TextStyle( + color: widget.color, + fontSize: widget.fontSize, + ), + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: widget.linkColor, + fontSize: widget.fontSize, + decoration: TextDecoration.underline, + decorationColor: widget.linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), ], ], diff --git a/lib/pages/chat/events/image_bubble.dart b/lib/pages/chat/events/image_bubble.dart index 4a77af18f..ea0439bec 100644 --- a/lib/pages/chat/events/image_bubble.dart +++ b/lib/pages/chat/events/image_bubble.dart @@ -79,12 +79,19 @@ class ImageBubble extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); - final borderRadius = + var borderRadius = this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius); final fileDescription = event.fileDescription; final textColor = this.textColor; + if (fileDescription != null) { + borderRadius = borderRadius.copyWith( + bottomLeft: Radius.zero, + bottomRight: Radius.zero, + ); + } + return Column( mainAxisSize: MainAxisSize.min, spacing: 8, @@ -122,21 +129,29 @@ class ImageBubble extends StatelessWidget { if (fileDescription != null && textColor != null) SizedBox( width: width, - child: Linkify( - text: fileDescription, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - style: TextStyle( - color: textColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, ), - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: linkColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, - decoration: TextDecoration.underline, - decorationColor: linkColor, + child: Linkify( + text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + style: TextStyle( + color: textColor, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + ), + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: linkColor, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), ), ], diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 68b84c9e6..c38639b60 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -149,10 +149,6 @@ class Message extends StatelessWidget { event.onlyEmotes && event.numberEmotes > 0 && event.numberEmotes <= 3); - final noPadding = { - MessageTypes.File, - MessageTypes.Audio, - }.contains(event.messageType); if (ownMessage) { color = @@ -338,12 +334,6 @@ class Message extends StatelessWidget { AppConfig.borderRadius, ), ), - padding: noBubble || noPadding - ? EdgeInsets.zero - : const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), constraints: const BoxConstraints( maxWidth: FluffyThemes.columnWidth * 1.5, diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 2df156bbc..116aaf4ef 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -185,19 +185,26 @@ class MessageContent extends StatelessWidget { if (event.messageType == MessageTypes.Emote) { html = '* $html'; } - return HtmlMessage( - html: html, - textColor: textColor, - room: event.room, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, - linkStyle: TextStyle( - color: linkColor, + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + child: HtmlMessage( + html: html, + textColor: textColor, + room: event.room, fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, - decoration: TextDecoration.underline, - decorationColor: linkColor, + linkStyle: TextStyle( + color: linkColor, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ); } // else we fall through to the normal message rendering @@ -276,25 +283,32 @@ class MessageContent extends StatelessWidget { final bigEmotes = event.onlyEmotes && event.numberEmotes > 0 && event.numberEmotes <= 3; - return Linkify( - text: event.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)), - hideReply: true, - ), - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - style: TextStyle( - color: textColor, - fontSize: bigEmotes ? fontSize * 5 : fontSize, - decoration: event.redacted ? TextDecoration.lineThrough : null, + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, ), - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: linkColor, - fontSize: fontSize, - decoration: TextDecoration.underline, - decorationColor: linkColor, + child: Linkify( + text: event.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)), + hideReply: true, + ), + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + style: TextStyle( + color: textColor, + fontSize: bigEmotes ? fontSize * 5 : fontSize, + decoration: + event.redacted ? TextDecoration.lineThrough : null, + ), + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: linkColor, + fontSize: fontSize, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ); } case EventTypes.CallInvite: @@ -351,13 +365,19 @@ class _ButtonContent extends StatelessWidget { @override Widget build(BuildContext context) { - return InkWell( - onTap: onPressed, - child: Text( - '$icon $label', - style: TextStyle( - color: textColor, - fontSize: fontSize, + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + child: InkWell( + onTap: onPressed, + child: Text( + '$icon $label', + style: TextStyle( + color: textColor, + fontSize: fontSize, + ), ), ), ); diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index 31a5c0708..80ae1cc08 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -30,85 +30,51 @@ class MessageDownloadContent extends StatelessWidget { ?.tryGet('mimetype') ?.toUpperCase() ?? 'UNKNOWN'); - final sizeString = event.sizeString; + final sizeString = event.sizeString ?? '?MB'; final fileDescription = event.fileDescription; - return Column( - mainAxisSize: MainAxisSize.min, - spacing: 8, - children: [ - InkWell( - onTap: () => event.saveFile(context), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - children: [ - Icon( - Icons.file_download_outlined, - color: textColor, - ), - const SizedBox(width: 16), - Flexible( - child: Text( - filename, - maxLines: 1, - style: TextStyle( - color: textColor, - fontWeight: FontWeight.bold, - ), - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - const Divider(height: 1), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), - child: Row( - children: [ - Text( - filetype, - style: TextStyle( - color: linkColor, - ), - ), - const Spacer(), - if (sizeString != null) - Text( - sizeString, - style: TextStyle( - color: linkColor, - ), - ), - ], - ), - ), - ], - ), - ), - if (fileDescription != null) - Linkify( - text: fileDescription, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - style: TextStyle( - color: textColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 8, + children: [ + OutlinedButton.icon( + style: OutlinedButton.styleFrom( + foregroundColor: textColor, + side: BorderSide(color: textColor), ), - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: linkColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, - decoration: TextDecoration.underline, - decorationColor: linkColor, + icon: const Icon(Icons.file_download_outlined), + label: Text( + '$sizeString | $filetype - $filename', + maxLines: 1, + overflow: TextOverflow.ellipsis, ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), + onPressed: () => event.saveFile(context), ), - ], + if (fileDescription != null) ...[ + Linkify( + text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + style: TextStyle( + color: textColor, + fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + ), + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: linkColor, + fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), + ), + ], + ], + ), ); } } diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 13f860609..e47979e80 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -189,21 +189,29 @@ class EventVideoPlayerState extends State { if (fileDescription != null && textColor != null && linkColor != null) SizedBox( width: width, - child: Linkify( - text: fileDescription, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - style: TextStyle( - color: textColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, ), - options: const LinkifyOptions(humanize: false), - linkStyle: TextStyle( - color: linkColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, - decoration: TextDecoration.underline, - decorationColor: linkColor, + child: Linkify( + text: fileDescription, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + style: TextStyle( + color: textColor, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + ), + options: const LinkifyOptions(humanize: false), + linkStyle: TextStyle( + color: linkColor, + fontSize: + AppConfig.fontSizeFactor * AppConfig.messageFontSize, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), ), ], diff --git a/lib/pages/chat_members/chat_members.dart b/lib/pages/chat_members/chat_members.dart index 4ca99ef31..d320f1431 100644 --- a/lib/pages/chat_members/chat_members.dart +++ b/lib/pages/chat_members/chat_members.dart @@ -70,7 +70,8 @@ class ChatMembersController extends State { .client .getRoomById(widget.roomId) ?.requestParticipants( - [...Membership.values]..remove(Membership.leave)); + [...Membership.values]..remove(Membership.leave), + ); if (!mounted) return; diff --git a/lib/utils/adaptive_bottom_sheet.dart b/lib/utils/adaptive_bottom_sheet.dart index cad4d525c..faa7f5ce8 100644 --- a/lib/utils/adaptive_bottom_sheet.dart +++ b/lib/utils/adaptive_bottom_sheet.dart @@ -1,8 +1,9 @@ import 'dart:math'; +import 'package:flutter/material.dart'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; -import 'package:flutter/material.dart'; Future showAdaptiveBottomSheet({ required BuildContext context, diff --git a/pubspec.lock b/pubspec.lock index 17bfb875f..2d95e487d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -90,10 +90,10 @@ packages: dependency: "direct main" description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" audio_session: dependency: transitive description: @@ -138,10 +138,10 @@ packages: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" canonical_json: dependency: transitive description: @@ -154,10 +154,10 @@ packages: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" charcode: dependency: transitive description: @@ -194,18 +194,18 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: "direct main" description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" colorize: dependency: transitive description: @@ -354,10 +354,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" ffi: dependency: transitive description: @@ -370,10 +370,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -1047,18 +1047,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -1135,10 +1135,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -1159,10 +1159,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" mgrs_dart: dependency: transitive description: @@ -1271,10 +1271,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider: dependency: "direct main" description: @@ -1383,10 +1383,10 @@ packages: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" platform_detect: dependency: transitive description: @@ -1463,10 +1463,10 @@ packages: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" proj4dart: dependency: transitive description: @@ -1780,10 +1780,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -1836,26 +1836,26 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" string_validator: dependency: transitive description: @@ -1900,34 +1900,34 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test: dependency: transitive description: name: test - sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.25.8" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.8" timezone: dependency: transitive description: @@ -2164,10 +2164,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.3.1" wakelock_plus: dependency: "direct main" description: @@ -2297,5 +2297,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.6.0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.27.0" diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 438aafbad..aefa9bf6e 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,21 +3,21 @@ # list(APPEND FLUTTER_PLUGIN_LIST - app_links - desktop_drop - dynamic_color - emoji_picker_flutter - file_selector_windows - flutter_secure_storage_windows - flutter_webrtc - geolocator_windows - pasteboard - permission_handler_windows - record_windows - share_plus - sqlcipher_flutter_libs - url_launcher_windows - window_to_front + app_links + desktop_drop + dynamic_color + emoji_picker_flutter + file_selector_windows + flutter_secure_storage_windows + flutter_webrtc + geolocator_windows + pasteboard + permission_handler_windows + record_windows + share_plus + sqlcipher_flutter_libs + url_launcher_windows + window_to_front ) list(APPEND FLUTTER_FFI_PLUGIN_LIST @@ -25,14 +25,14 @@ list(APPEND FLUTTER_FFI_PLUGIN_LIST set(PLUGIN_BUNDLED_LIBRARIES) -foreach (plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach (plugin) +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) -foreach (ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach (ffi_plugin) +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) From 1b42cf44fc83ac45433b1c1822ec2d2e86e5799d Mon Sep 17 00:00:00 2001 From: krille-chan Date: Sat, 19 Apr 2025 09:44:53 +0200 Subject: [PATCH 18/20] chore: Follow up message design --- lib/pages/chat/events/html_message.dart | 2 +- lib/pages/chat/events/message.dart | 37 +++++---- .../chat/events/message_download_content.dart | 78 +++++++++++++------ lib/pages/chat/events/reply_content.dart | 12 +-- .../events/verification_request_content.dart | 72 ----------------- lib/pages/chat/reply_display.dart | 1 - 6 files changed, 83 insertions(+), 119 deletions(-) delete mode 100644 lib/pages/chat/events/verification_request_content.dart diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index d40ac72a7..7aca3154b 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -250,7 +250,7 @@ class HtmlMessage extends StatelessWidget { border: Border( left: BorderSide( color: textColor, - width: 3, + width: 5, ), ), ), diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index c38639b60..823594a1a 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -20,7 +20,6 @@ import 'message_content.dart'; import 'message_reactions.dart'; import 'reply_content.dart'; import 'state_message.dart'; -import 'verification_request_content.dart'; class Message extends StatelessWidget { final Event event; @@ -85,7 +84,7 @@ class Message extends StatelessWidget { if (event.type == EventTypes.Message && event.messageType == EventTypes.KeyVerificationRequest) { - return VerificationRequestContent(event: event, timeline: timeline); + return StateMessage(event); } final client = Matrix.of(context).client; @@ -376,22 +375,32 @@ class Message extends StatelessWidget { return Padding( padding: const EdgeInsets.only( - bottom: 4.0, + left: 16, + right: 16, + top: 8, ), - child: InkWell( + child: Material( + color: + Colors.transparent, borderRadius: ReplyContent .borderRadius, - onTap: () => - scrollToEventId( - replyEvent.eventId, - ), - child: AbsorbPointer( - child: ReplyContent( - replyEvent, - ownMessage: - ownMessage, - timeline: timeline, + child: InkWell( + borderRadius: + ReplyContent + .borderRadius, + onTap: () => + scrollToEventId( + replyEvent.eventId, + ), + child: AbsorbPointer( + child: ReplyContent( + replyEvent, + ownMessage: + ownMessage, + timeline: + timeline, + ), ), ), ), diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index 80ae1cc08..b1b0dd71f 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -32,31 +32,59 @@ class MessageDownloadContent extends StatelessWidget { 'UNKNOWN'); final sizeString = event.sizeString ?? '?MB'; final fileDescription = event.fileDescription; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - spacing: 8, - children: [ - OutlinedButton.icon( - style: OutlinedButton.styleFrom( - foregroundColor: textColor, - side: BorderSide(color: textColor), - ), - icon: const Icon(Icons.file_download_outlined), - label: Text( - '$sizeString | $filetype - $filename', - maxLines: 1, - overflow: TextOverflow.ellipsis, + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 8, + children: [ + Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), + onTap: () => event.saveFile(context), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 16, + children: [ + CircleAvatar( + backgroundColor: textColor.withAlpha(32), + child: Icon(Icons.file_download_outlined, color: textColor), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + filename, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: textColor, + fontWeight: FontWeight.w500, + ), + ), + Text( + '$sizeString | $filetype', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: textColor, fontSize: 10), + ), + ], + ), + ], + ), ), - onPressed: () => event.saveFile(context), ), - if (fileDescription != null) ...[ - Linkify( + ), + if (fileDescription != null) ...[ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Linkify( text: fileDescription, textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( @@ -72,9 +100,9 @@ class MessageDownloadContent extends StatelessWidget { ), onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - ], + ), ], - ), + ], ); } } diff --git a/lib/pages/chat/events/reply_content.dart b/lib/pages/chat/events/reply_content.dart index e5b7f2975..65c8cabdb 100644 --- a/lib/pages/chat/events/reply_content.dart +++ b/lib/pages/chat/events/reply_content.dart @@ -10,14 +10,12 @@ class ReplyContent extends StatelessWidget { final Event replyEvent; final bool ownMessage; final Timeline? timeline; - final Color? backgroundColor; const ReplyContent( this.replyEvent, { this.ownMessage = false, super.key, this.timeline, - this.backgroundColor, }); static const BorderRadius borderRadius = BorderRadius.only( @@ -40,16 +38,18 @@ class ReplyContent extends StatelessWidget { : theme.colorScheme.tertiary; return Material( - color: backgroundColor ?? - theme.colorScheme.surface.withAlpha(ownMessage ? 50 : 80), + color: Colors.transparent, borderRadius: borderRadius, child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( - width: 3, + width: 5, height: fontSize * 2 + 16, - color: color, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + color: color, + ), ), const SizedBox(width: 6), Flexible( diff --git a/lib/pages/chat/events/verification_request_content.dart b/lib/pages/chat/events/verification_request_content.dart deleted file mode 100644 index 9b085114f..000000000 --- a/lib/pages/chat/events/verification_request_content.dart +++ /dev/null @@ -1,72 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; - -import '../../../config/app_config.dart'; - -class VerificationRequestContent extends StatelessWidget { - final Event event; - final Timeline timeline; - - const VerificationRequestContent({ - required this.event, - required this.timeline, - super.key, - }); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - final events = event.aggregatedEvents(timeline, 'm.reference'); - final done = events.where((e) => e.type == EventTypes.KeyVerificationDone); - final start = - events.where((e) => e.type == EventTypes.KeyVerificationStart); - final cancel = - events.where((e) => e.type == EventTypes.KeyVerificationCancel); - final fullyDone = done.length >= 2; - final started = start.isNotEmpty; - final canceled = cancel.isNotEmpty; - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 4.0, - ), - child: Center( - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - border: Border.all( - color: theme.dividerColor, - ), - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - color: theme.colorScheme.surface, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Icon( - Icons.lock_outlined, - color: canceled - ? Colors.red - : (fullyDone ? Colors.green : Colors.grey), - ), - const SizedBox(width: 8), - Text( - canceled - ? 'Error ${cancel.first.content.tryGet('code')}: ${cancel.first.content.tryGet('reason')}' - : (fullyDone - ? L10n.of(context).verifySuccess - : (started - ? L10n.of(context).loadingPleaseWait - : L10n.of(context).newVerificationRequest)), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/chat/reply_display.dart b/lib/pages/chat/reply_display.dart index ec607e1ac..361f5b97b 100644 --- a/lib/pages/chat/reply_display.dart +++ b/lib/pages/chat/reply_display.dart @@ -38,7 +38,6 @@ class ReplyDisplay extends StatelessWidget { ? ReplyContent( controller.replyEvent!, timeline: controller.timeline!, - backgroundColor: Colors.transparent, ) : _EditContent( controller.editEvent?.getDisplayEvent(controller.timeline!), From b895ca55238beda0949f01c17e0758b662be50cc Mon Sep 17 00:00:00 2001 From: Krille Date: Sat, 19 Apr 2025 14:14:51 +0200 Subject: [PATCH 19/20] chore: Follow up file message design Signed-off-by: Krille --- lib/pages/chat/events/message_download_content.dart | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index b1b0dd71f..6e37f00b9 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -1,12 +1,10 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_linkify/flutter_linkify.dart'; -import 'package:matrix/matrix.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/utils/file_description.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/url_launcher.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; +import 'package:matrix/matrix.dart'; class MessageDownloadContent extends StatelessWidget { final Event event; @@ -42,7 +40,8 @@ class MessageDownloadContent extends StatelessWidget { child: InkWell( borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), onTap: () => event.saveFile(context), - child: Padding( + child: Container( + width: 400, padding: const EdgeInsets.all(16.0), child: Row( mainAxisSize: MainAxisSize.min, From 8dd1b6dd8b96703b33c29c7a394acb88614385c1 Mon Sep 17 00:00:00 2001 From: Krille Date: Sat, 19 Apr 2025 14:17:48 +0200 Subject: [PATCH 20/20] build: Bump version to 1.26.0 Signed-off-by: Krille --- CHANGELOG.md | 376 +++++++++++++++++++++++++++++++++++++++++++++------ pubspec.yaml | 2 +- 2 files changed, 337 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cbc85fd0..58fb6fe53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,81 @@ +## v1.26.0 + +- feat: Add advanced configuration page (Krille) +- feat: clearly mark when a video is to be downloaded (Rafał Hirsch) +- feat: Filter for room members page and easier approve knocking users (Krille) +- feat: Navigate in image viewer with keyboard keys (krille-chan) +- feat: New video file picker button (Krille) +- feat: Send optional message with images or files (Krille) +- feat: support inline video playback on macOS (Rafał Hirsch) +- build: Flutter 3.29.3 (Krille) +- build: Update gorouter package (Krille) +- build: Update kotlin gradle plugin (Krille) +- build: Update matrix dart sdk (Krille) +- build: Update openssl to 0.5.0 (Krille) +- build: use singleInstance as launchmode (krille-chan) +- chore: Add matrix notifications for issues (Krille) +- chore: Better error handling for image rendering (krille-chan) +- chore: Better no compression supported UX (Krille) +- chore: Correct availability of desktop builds (Lenni) +- chore: disable echoCancel for audio messages (Krille) +- chore: divider when scrolled up (krille-chan) +- chore: Improve avatar designg (Krille) +- chore: Make push gateway configurable (Krille) +- chore: Nicer colors for reactions (krille-chan) +- chore: Nicer scaffold dialog for column mode (Krille) +- chore: Simpler changing config variables (Krille) +- chore: Update locale config for localizations (Krille) +- chore: Update pubspec.lock (Krille) +- chore: upgrade chewie and video_player packages (Rafał Hirsch) +- chore: Use Cupertino Activity Indicator in ChatEventList (krille-chan) +- chore: Use other join endpoint for room upgrades (Krille) +- fix(macos): update dependencies to make the build work (Rafał Hirsch) +- fix: Add missing html tag to render (Krille) +- fix: Consistent element padding between server picker and login view (xegim) +- fix: Index of numbered lists are off (Krille) +- fix: never use a transition on the shell route (Rafał Hirsch) +- fix: Null error in ClientChooserButton (krille-chan) +- fix: prevent users from creating spaces with empty names (ggurdin) +- fix: properly dispose VideoPlayerController (Rafał Hirsch) +- fix: Remove too sensitive dismiss gesture on chat list items (Krille) +- fix: Text scale factor in Linkify widgets (Krille) +- fix: update condition in account deletion function to allow deletion to go through (ggurdin) +- refactor: Easier shift enter logic for text input (Krille) +- refactor: Formatting (Krille) +- refactor: Implement avatar image viewer and adjust design (Krille) +- refactor: Improved UX for room upgrades (Krille) +- refactor: Migrate more config options to config viewer (Krille) +- refactor: Move public room bottom sheet into dialog (Krille) +- refactor: Remove custom font and emoji font workaround (krille-chan) +- refactor: Replace user bottom sheet with menu and small dialog (Krille) +- Added translation using Weblate (Telugu) (katakam chakri) +- Translated using Weblate (Basque) (xabirequejo) +- Translated using Weblate (Chinese (Simplified Han script)) (Poesty Li) +- Translated using Weblate (Chinese (Simplified Han script)) (大王叫我来巡山) +- Translated using Weblate (Chinese (Traditional Han script)) (Mare JP) +- Translated using Weblate (Chinese (Traditional Han script)) (miullu) +- Translated using Weblate (Dutch) (Jelv) +- Translated using Weblate (Estonian) (Priit Jõerüüt) +- Translated using Weblate (Filipino) (searinminecraft) +- Translated using Weblate (French) (Antonin Del Fabbro) +- Translated using Weblate (Galician) (josé m) +- Translated using Weblate (German) (nautilusx) +- Translated using Weblate (German) (Very Able) +- Translated using Weblate (Indonesian) (Linerly) +- Translated using Weblate (Irish) (Aindriú Mac Giolla Eoin) +- Translated using Weblate (Italian) (Angelo Schirinzi) +- Translated using Weblate (Korean) (kdh8219) +- Translated using Weblate (Latvian) (Edgars Andersons) +- Translated using Weblate (Latvian) (ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝)) +- Translated using Weblate (Polish) (Piotr Orzechowski) +- Translated using Weblate (Russian) (Yurt Page) +- Translated using Weblate (Spanish) (José Muñoz) +- Translated using Weblate (Spanish) (Kimby) +- Translated using Weblate (Telugu) (katakam chakri) +- Translated using Weblate (Ukrainian) (Ihor Hordiichuk) + ## v1.25.0 + - feat: Display all push rules and allow to enable disable them (Krille) - feat: Inspect and delete push rules (Krille) - feat: Pick share keys with (Krille) @@ -74,6 +151,7 @@ - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.24.0 + - build: Add missing libssl library (krille-chan) - build: Update dart_webrtc package (Krille) - build: Update matrix sdk and dependencies (Krille) @@ -118,6 +196,7 @@ - Translated using Weblate (Vietnamese) (Tewuzij) ## v1.23.0 + - design: Highlight emoji only messages (Krille) - design: New login design (Krille) - docs: fix snapstore badge on website (Krille) @@ -181,9 +260,12 @@ ## v1.22.0 -FluffyChat v1.22.0 brings a new design for spaces, replaces the bottom navigation bar with filter chips and makes it finally possible to play ogg audio messages on iOS. A lot of other fixes and improvements have also been added to this release. +FluffyChat v1.22.0 brings a new design for spaces, replaces the bottom navigation bar with filter +chips and makes it finally possible to play ogg audio messages on iOS. A lot of other fixes and +improvements have also been added to this release. -FluffyChat also now uses the new authenticated media endpoints if the server supports Matrix v1.11 or +FluffyChat also now uses the new authenticated media endpoints if the server supports Matrix v1.11 +or mentions the msc with the key `org.matrix.msc3916.stable` in the `unstable_features`. - design: Add snackbar with link to changelog on new version (Krille) @@ -259,6 +341,7 @@ mentions the msc with the key `org.matrix.msc3916.stable` in the `unstable_featu - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.21.2 + Updates the Matrix Dart SDK to fix some minor bugs. - Added translation using Weblate (Lojban) (Zig-Rust-Odin) @@ -281,6 +364,7 @@ Updates the Matrix Dart SDK to fix some minor bugs. - Translated using Weblate (Turkish) (Oğuz Ersen) ## v1.21.1 + - build: Update Matrix Dart SDK (Krille) - build: Update to Flutter 3.22.2 (krille-chan) - feat: add option to configure reply swipe direction (MrSpoony) @@ -294,7 +378,10 @@ Updates the Matrix Dart SDK to fix some minor bugs. - Translated using Weblate (Vietnamese) (Karo) ## v1.21.0 -FluffyChat v1.21.0 introduces the new search feature which also includes a gallery and files list for each chat. Several performance improvements have been added under the hood, leading to a much nicer user experience. + +FluffyChat v1.21.0 introduces the new search feature which also includes a gallery and files list +for each chat. Several performance improvements have been added under the hood, leading to a much +nicer user experience. - feat: Enable download images on iOS, not only share images (krille-chan) - feat: Search feature (krille-chan) @@ -323,7 +410,8 @@ FluffyChat v1.21.0 introduces the new search feature which also includes a galle - refactor: Delete database file on failed app start (krille-chan) - refactor: Display better command hints (Krille) - refactor: Improve performance of chat list (krille-chan) -- refactor: Precache theme and directchatmatrixid to improve performance in chat list item (krille-chan) +- refactor: Precache theme and directchatmatrixid to improve performance in chat list item ( + krille-chan) - refactor: Update to Matrix Dart SDK 0.29.9 (Krille) - Translated using Weblate (Croatian) (Milo Ivir) - Translated using Weblate (Czech) (Jozef Mlich) @@ -335,6 +423,7 @@ FluffyChat v1.21.0 introduces the new search feature which also includes a galle - Translated using Weblate (Turkish) (Oğuz Ersen) ## v1.20.0 + Design improvements and new advanced UI to manage rooms. - build: Fix google services patch (Krille) @@ -369,6 +458,7 @@ Design improvements and new advanced UI to manage rooms. - Translated using Weblate (Portuguese (Brazil)) (Rudah Ximenes Alvarenga) ## v1.19.2 + Bugfix release to mostly fix the new database encryption on Linux and update the translations. - build: (deps): bump peaceiris/actions-gh-pages from 3 to 4 (dependabot[bot]) @@ -376,7 +466,8 @@ Bugfix release to mostly fix the new database encryption on Linux and update the - build: Update emoji picker package (krille-chan) - build: Update flutter_map package (krille-chan) - docs: Fix typo in android app description (Krille) -- fix: Allow unencrypted database if gnome keyring not present or platform does not support it (krille-chan) +- fix: Allow unencrypted database if gnome keyring not present or platform does not support it ( + krille-chan) - fix: Background color of images with transparency (Krille) - fix: Localizations from weblate confused by unknownEvent locale (Krille) - fix: More logs when database fails to init and trycatch sendInitNotification (Krille) @@ -406,6 +497,7 @@ Bugfix release to mostly fix the new database encryption on Linux and update the - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.19.1 + Minor bugfix release for login with SSO on web. - feat: Show/hide third column in chat view (krille-chan) @@ -417,7 +509,9 @@ Minor bugfix release for login with SSO on web. - refactor: new flutter only typing animation (krille-chan) ## v1.19.0 -FluffyChat v1.19.0 features an improved design for message bubbles and a lot of fixes under the hood. + +FluffyChat v1.19.0 features an improved design for message bubbles and a lot of fixes under the +hood. - build: Update matrix dart sdk (Krille) - build: Update to flutter 3.19.5 (krille-chan) @@ -439,7 +533,8 @@ FluffyChat v1.19.0 features an improved design for message bubbles and a lot of - feat: Add insert content via gboard (krille-chan) - feat: Reply with one button in desktop (krille-chan) - fix: Do not sync in background mode (krille-chan) -- fix: FluffyChat should assume m.change_password capabilitiy is supported if not present per spec (krille-chan) +- fix: FluffyChat should assume m.change_password capabilitiy is supported if not present per spec ( + krille-chan) - fix: never use root navigator for bottom sheets (The one with the braid) - fix: Remove pantalaimon message with normal error message (krille-chan) - fix: Search in spaces view (krille-chan) @@ -454,6 +549,7 @@ FluffyChat v1.19.0 features an improved design for message bubbles and a lot of - Translated using Weblate (Interlingua) (Software In Interlingua) ## v1.18.0 + - feat: Add speed button for audioplayer (krille-chan) - feat: enhanced send video functionality by adding toggle send original (Mubeen Rizvi) - feat: add dialog to hide presence list with long-press (Marcus Hoffmann) @@ -492,6 +588,7 @@ FluffyChat v1.19.0 features an improved design for message bubbles and a lot of - Translated using Weblate (Ukrainian) (Сергій) ## v1.17.3 + - feat: New account data based wallpaper feature (Krille) - build: Update dependencies (Krille) - build: Update flutter to 3.16.9 (Krille) @@ -509,6 +606,7 @@ FluffyChat v1.19.0 features an improved design for message bubbles and a lot of - fix: Share invite links of public rooms (Krille) ## v1.17.2 + Another minor bugfix release which also implements private read receipts. - feat: Implement private read receipts (krille-chan) @@ -538,6 +636,7 @@ Another minor bugfix release which also implements private read receipts. - Translated using Weblate (Ukrainian) (Сергій) ## v1.17.1 + Minor bugfix release. - build: Update matrix sdk 0.25.5 (Krille) @@ -545,13 +644,17 @@ Minor bugfix release. - chore: Remove vibration on iOS for long press (Krille) - design: Better paddings in tablet mode (krille-chan) - docs: Fix typo in readme (Krille) -- Fix dependency. missing yq when invoking setup-web. also ensure updated config.json copied in (Isaac Johnson) +- Fix dependency. missing yq when invoking setup-web. also ensure updated config.json copied in ( + Isaac Johnson) - fix: text nodes with multiple links crash the timeline (Krille) - fix: URL too long when reporting bug (Krille) - fix: Wait for user device keys before start verification (Krille) ## v1.17.0 -FluffyChat v1.17.0 refreshes the overall user experience, changes some design and fixes a lot of bugs. It also replaces the stories feature with matrix presences, introduces a new kind of database to store the messages locally and improves the performance and app stability. + +FluffyChat v1.17.0 refreshes the overall user experience, changes some design and fixes a lot of +bugs. It also replaces the stories feature with matrix presences, introduces a new kind of database +to store the messages locally and improves the performance and app stability. - change: Remove wallpaper feature (krille-chan) - design: Adjust login page design (krille-chan) @@ -605,9 +708,11 @@ FluffyChat v1.17.0 refreshes the overall user experience, changes some design an - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.16.1 + Test candidate for the new database. ## v1.16.0 + - build: Set olm to 1.3.2 to fix android build (krille-chan) - build: Update dependencies (krille-chan) - build: Update flutter_olm (Krille) @@ -768,6 +873,7 @@ Test candidate for the new database. - Translated using Weblate (Vietnamese) (Sorunome) ## v1.15.1 + - feat: Make all text in chat selectable on desktop (krille-chan) - chore: Add border to images in timeline (krille-chan) - chore: added android audio sharing intent (Aryan Arora) @@ -793,6 +899,7 @@ Test candidate for the new database. - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.15.0 + - feat: Add experimental todo list for rooms (krille-chan) - feat: better scroll to last read message handling (krille-chan) - build: Add appid suffix to android debug builds (krille-chan) @@ -806,13 +913,15 @@ Test candidate for the new database. - design: Make incoming messages color more light (krille-chan) - design: Make key verification an adaptive dialog (krille-chan) - design: Make own chat bubble primary color for better contrast (krille-chan) -- fix: Create chat dialog crashes sometimes and power level textfield does not validate input (krille-chan) +- fix: Create chat dialog crashes sometimes and power level textfield does not validate input ( + krille-chan) - fix: Remove uncompatible dependencies connectivity_plus and wakelock (Krille) - fix: Use correct localization for redactedBy (krille-chan) - fix: noFCM warning dialog (krille-chan) - fix: render tg-forward as blockquote style (krille-chan) - fix: Archive does not update its state -- refactor: Change audio codec to opus where supported to have better compatibility with Element (Krille) +- refactor: Change audio codec to opus where supported to have better compatibility with Element ( + Krille) - refactor: Make file dialog adaptive and adjust design (krille-chan) - refactor: Preload notification sound on web (Krille) - refactor: Remove unused config (krille-chan) @@ -832,10 +941,12 @@ Test candidate for the new database. - Translated using Weblate (Thai) (Amy/Atius) ## v1.14.5 + - Hotfix iOS crashes on start - Hotfix cannot reset applock ## v1.14.4 + Minor bugfix release. Please note that because of a Flutter update FluffyChat is no longer compatible with iOS 11. @@ -851,17 +962,24 @@ compatible with iOS 11. - refactor: Only preload client for GUI start (krille-chan) ## v1.14.3 + - hotfix app lock still displayed even when account is logged out - Update to Flutter 3.13.6 ## v1.14.2 + - hotfix for broken applock screen ## v1.14.1 + - fix: Routing bug when adding second account via password login ## v1.14.0 -Release with a lot of bugfixes and refactorings under the hood. FluffyChat now uses go_router instead of vrouter, works with the newest Flutter SDK and supports "reason" field for redactions. For Android there is a new "background-fetch mode" for Push Notifications which should make notifications in background faster and more reliable and reduce battery-usage. + +Release with a lot of bugfixes and refactorings under the hood. FluffyChat now uses go_router +instead of vrouter, works with the newest Flutter SDK and supports "reason" field for redactions. +For Android there is a new "background-fetch mode" for Push Notifications which should make +notifications in background faster and more reliable and reduce battery-usage. - feat: Background fetch mode on Android (krille-chan) - feat: Improved mouse support for selecting events (krille-chan) @@ -927,6 +1045,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - Translated using Weblate (Ukrainian) (Skrripy) ## v1.13.0 + - feat: option to not send typing notifications (Bnyro) - feat: small performance tweaks for Message (gilice) - feat: New onboarding screen with SSO as first class feature @@ -934,7 +1053,8 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - fix: Set iOS badge (Krille) - refactor: Switch the dev hosting platform from GitLab to GitHub - design: New more compact chat bubble design and other design tweaks -- design: Login now shows SSO more prominent and deprecates in-app registration in favor of SSO registration +- design: Login now shows SSO more prominent and deprecates in-app registration in favor of SSO + registration - Translated using Weblate (Arabic) (Rex_sa) - Translated using Weblate (Chinese (Simplified)) (Poesty Li) - Translated using Weblate (Estonian) (Priit Jõerüüt) @@ -943,6 +1063,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.12.0 + - Added translation using Weblate (Toki Pona) (Mæve Rey) - Translated using Weblate (Arabic) (Rex_sa) - Translated using Weblate (Chinese (Simplified)) (Eric) @@ -980,12 +1101,14 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - feat: Add toggle to mute notifications from chat groups (fbievan) - feat: Allow ruby tags in html (Krille) - feat: Display progress value for initial sync (Krille) -- feat: Implement new error reporting tool when critical features break like playing audio or video messages or opening a chat (Krille) +- feat: Implement new error reporting tool when critical features break like playing audio or video + messages or opening a chat (Krille) - feat: clean up macOS build metadata (TheOneWithTheBraid) - feat: set display information correctly (TheOneWithTheBraid) - feat: update macOS build files (TheOneWithTheBraid) - feat: update macOS build information for macOS Ventura (TheOneWithTheBraid) -- fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a VRouter." (Lauren N. Liberda) +- fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a + VRouter." (Lauren N. Liberda) - fix: Broken arb file (Krille) - fix: Do not unnecessary request all members in public rooms (Krille) - fix: Remove wrong rendered linebreak in html (Krille) @@ -1007,6 +1130,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - refactor: Use DateTime for weekday localization (Malin Errenst) ## v1.11.2 + - Translated using Weblate (Croatian) (Milo Ivir) - Translated using Weblate (Dutch) (Jelv) - Translated using Weblate (Estonian) (Priit Jõerüüt) @@ -1018,9 +1142,11 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - fix: Chats do not load (Krille) ## v1.11.1 - 2023-04-20 + - fix: Download files on web and iOS with correct mimetype ## v1.11.0 - 2023-04-14 + - feat: Add visual read marker (Krille) - feat: Jump to last read event (Krille) - feat: Use fragmented timeline to jump to event (Krille) @@ -1051,6 +1177,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.10.0 - 2023-02-25 + - Added translation using Weblate (Thai) (Wphaoka) - Added translation using Weblate (Tibetan) (Nathan Freitas) - Default hardcoded message when l10n is not available (fabienli) @@ -1088,7 +1215,8 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - fix: Display error when user tries to send too large file (Christian Pauly) - refactor: Do only instantiate AudioPlayer() object when in use (Christian Pauly) - refactor: Remove syncstatus verbose logs (Christian Pauly) -- refactor: Store cached files in tmp directory so OS will clear file cache from time to time (Krille) +- refactor: Store cached files in tmp directory so OS will clear file cache from time to time ( + Krille) - style: Adjust key verification dialog (Christian Pauly) - style: Bootstrap design adjustments (Christian Pauly) - style: Encryption page adjustments (Christian Pauly) @@ -1105,6 +1233,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - utils/url_launcher: force opening http(s) links in external browser (Marcus Hoffmann) ## v1.9.0 - 2023-01-29 + - Translated using Weblate (Czech) (Michal Bedáň) - Translated using Weblate (Czech) (grreby) - Translated using Weblate (Dutch) (Jelv) @@ -1143,6 +1272,7 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - style: Redesign public room bottomsheets (Krille) ## v1.8.0 2022-12-30 + - Added translation using Weblate (Yue (yue_HK)) (Raatty) - Translated using Weblate (Chinese (Simplified)) (Mike Evans) - Translated using Weblate (Estonian) (Priit Jõerüüt) @@ -1169,13 +1299,19 @@ Release with a lot of bugfixes and refactorings under the hood. FluffyChat now u - fix: minor issues in room list (TheOneWithTheBraid) ## v1.7.2 2022-12-19 + Update dependencies and translations. ## v1.7.1 2022-11-23 -Minor bugfix release to retrigger build for FlatPak and Android. Fixes some style bugs and updates some translations + +Minor bugfix release to retrigger build for FlatPak and Android. Fixes some style bugs and updates +some translations ## v1.7.0 2022-11-17 -FluffyChat 1.7.0 features a new way to work with spaces via a bottom navigation bar. A lot of work has also been done under the hood to make the app faster and more stable. The main color has slightly changed and the design got some finetuning. + +FluffyChat 1.7.0 features a new way to work with spaces via a bottom navigation bar. A lot of work +has also been done under the hood to make the app faster and more stable. The main color has +slightly changed and the design got some finetuning. - chore: Add keys to roomlist and stories header (Christian Pauly) - chore: Add unread badge to navigation rail and adjust design (Christian Pauly) @@ -1232,6 +1368,7 @@ FluffyChat 1.7.0 features a new way to work with spaces via a bottom navigation - Translated using Weblate (Ukrainian) (Raatty) ## v1.6.4 - 2022-09-08 + - Translated using Weblate (Chinese (Simplified)) (Eric) - Translated using Weblate (Estonian) (Priit Jõerüüt) - Translated using Weblate (Galician) (Xosé M) @@ -1247,6 +1384,7 @@ FluffyChat 1.7.0 features a new way to work with spaces via a bottom navigation - fix: add missing command localizations (Christian Pauly) ## v1.6.3 - 2022-08-25 + - Translated using Weblate (Chinese (Simplified)) (Eric) - Translated using Weblate (Estonian) (Priit Jõerüüt) - Translated using Weblate (Finnish) (Aminda Suomalainen) @@ -1259,6 +1397,7 @@ FluffyChat 1.7.0 features a new way to work with spaces via a bottom navigation - refactor: App widget (Christian Pauly) ## v1.6.0 - 2022-07-31 + FluffyChat 1.6.0 features a lot of bug fixes and improvements. The code base has been simplified and the drawer on the chat list page got a come-back. Some new features like the space hierarchy and session dump have been implemented. @@ -1329,6 +1468,7 @@ the space hierarchy and session dump have been implemented. - chore: remove snapping sheet (TheOneWithTheBraid) ## v1.5.0 - 2022-06-03 + - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) - feat: Better sign up UX and allow signup without password (Christian Pauly) - feat: Initial material you support (Christian Pauly) @@ -1364,6 +1504,7 @@ the space hierarchy and session dump have been implemented. - Translated using Weblate (Turkish) (Oğuz Ersen) ## v1.4.0 - 2022-04-23 + - design: Display icon for failed sent messages (Krille Fear) - design: Display own stories at first place and combine with new stories button (Krille Fear) - feat: Add "Show related DMs in spaces" settings (20kdc) @@ -1418,6 +1559,7 @@ the space hierarchy and session dump have been implemented. - refactor: New push (Krille Fear) ## v1.3.1 - 2022-03-20 + - Allow app to be moved to external storage (Marcel) - Translated using Weblate (Arabic) (Mads Louis) - Translated using Weblate (Basque) (Sorunome) @@ -1456,14 +1598,19 @@ the space hierarchy and session dump have been implemented. - refactor: Switch to just audio for playing sounds (Krille Fear) ## v1.3.0 - 2022-02-12 -FluffyChat 1.3.0 makes it possible to report offensive users to server admins (not only messages). It fixes + +FluffyChat 1.3.0 makes it possible to report offensive users to server admins (not only messages). +It fixes the video player, improves Linux desktop notifications, and the stories design. -The button to create a new story is now in the app bar of the main page so that users who don't want to use +The button to create a new story is now in the app bar of the main page so that users who don't want +to use this feature no longer have a whole list item pinned at the top of the chat list. -FluffyChat 1.3.0 is the first release with full null safe dart code. While this is a huge change under the -hood, it should improve the stability and performance of the app. It also builds now with Flutter 2.10. +FluffyChat 1.3.0 is the first release with full null safe dart code. While this is a huge change +under the +hood, it should improve the stability and performance of the app. It also builds now with Flutter +2.10. Thanks to all contributors and translators!! <3 @@ -1503,6 +1650,7 @@ Thanks to all contributors and translators!! <3 - refactor: Migrate to null safety (Krille Fear) ## v1.2.0 - 2022-01-27 + FluffyChat 1.2.0 brings a new stories feature, a lot of bug fixes and improved voice messages. @@ -1536,7 +1684,8 @@ voice messages. - followup: Improve stories (Krille Fear) - Improve website SEO tagging (Marcel) - Increase font size granularity (S1m) -- refactor: /command hints add tooltips, test for missing hints, script to generate glue code, hints for dm, create, clearcache, discardsession (Steef Hegeman) +- refactor: /command hints add tooltips, test for missing hints, script to generate glue code, hints + for dm, create, clearcache, discardsession (Steef Hegeman) - refactor: Make more files null safe (Krille Fear) - refactor: Make style settings null safe (Krille Fear) - systemNavigationBarColor ← appBar.backgroundColor (Steef Hegeman) @@ -1566,6 +1715,7 @@ voice messages. - Translated using Weblate (Ukrainian) (Ihor Hordiichuk) ## v1.1.0 - 2021-12-08 + - CI: Add candidate release pipeline (Krille Fear) - Translated using Weblate (Dutch) (Jelv) - Translated using Weblate (Estonian) (Priit Jõerüüt) @@ -1586,6 +1736,7 @@ voice messages. - refactor: Make user device list item null safe (Krille Fear) ## v1.0.0 - 2021-11-29 + - design: Chat backup dialog as a banner - design: Encrypted by design, all users valid is normal not green - design: Move video call button to menu @@ -1643,7 +1794,9 @@ voice messages. - fix: Wrong version in snap packages ## v0.42.2 - 2021-11-04 -Minor bugfix release which fixes signing up on matrix.org and make FluffyChats voice messages playable in Element. + +Minor bugfix release which fixes signing up on matrix.org and make FluffyChats voice messages +playable in Element. - feat: Nicer registration form - feat: Nicer audio message design and send duration @@ -1653,6 +1806,7 @@ Minor bugfix release which fixes signing up on matrix.org and make FluffyChats v - fix: Crash on logout ## v0.42.1 - 2021-10-26 + Minor bugfix release. - feat: Ignore users directly from bottom sheet @@ -1663,6 +1817,7 @@ Minor bugfix release. - design: Make homepicker page nicer ## v0.42.0 - 2021-10-14 + This release fixes several bugs and makes E2EE enabled by default. - feat: Enable E2EE by default for new rooms @@ -1673,17 +1828,20 @@ This release fixes several bugs and makes E2EE enabled by default. - feat: More finetuning for font sizes - chore: Updated translations (Thanks to all translators!) - fix: App crash on logout -- fix: Temporary disable sign-up for matrix.org (Currently gives "500: Internal Server Error" while FluffyChat **should** send the same requests like Element) +- fix: Temporary disable sign-up for matrix.org (Currently gives "500: Internal Server Error" while + FluffyChat **should** send the same requests like Element) - fix: Implement Roboto font to fix font issues on Linux Desktop and mobile - fix: QR Code scanning ## v0.41.3 - 2021-10-08 + Minor bugfix release. - fix: Last space is not visible - chore: Google services disabled by default for F-Droid ## v0.41.1 - 2021-09-15 + Minor bugfix release. - fix: Start up time waits for first sync @@ -1693,7 +1851,10 @@ Minor bugfix release. And some other minor bugs. ## v0.41.0 - 2021-09-14 -This release features a lot of bug fixes and the new multi account feature which also include account bundles. + +This release features a lot of bug fixes and the new multi account feature which also include +account bundles. + - feat: Multiple accounts - feat: New splash screen - fix: Password reset @@ -1705,21 +1866,28 @@ This release features a lot of bug fixes and the new multi account feature which - chore: Updated translations ## v0.40.1 - 2021-09-14 + Minor bug fixes. ## v0.40.0 - 2021-09-13 -This release contains a security fix. Red more about it here: https://matrix.org/blog/2021/09/13/vulnerability-disclosure-key-sharing + +This release contains a security fix. Red more about it +here: https://matrix.org/blog/2021/09/13/vulnerability-disclosure-key-sharing - New in-app registration - Design improvements - Minor fixes ## v0.39.0 - 2021-08-30 + - Hotfix a bug which produces problems in downloading files and playing audios - Hotfix a bug which breaks device management ## v0.39.0 - 2021-08-28 -This release fixes a bug which makes it impossible to send images in unencrypted rooms. It also implements a complete new designed new chat page which now uses a QR code based workflow to start a new chat. + +This release fixes a bug which makes it impossible to send images in unencrypted rooms. It also +implements a complete new designed new chat page which now uses a QR code based workflow to start a +new chat. - feat: Dismiss keyboard on scroll in iOS - feat: Implement QR code scanner @@ -1732,11 +1900,13 @@ This release fixes a bug which makes it impossible to send images in unencrypted - fix: Open matrix.to urls - fix: Padding and colors - fix: Sharing invite link -- fix: Unread bubbles on iOS +- fix: Unread bubbles on iOS - fix: Sending images in unencrypted rooms ## v0.38.0 - 2021-08-22 -This release adds more functionality for spaces, enhances the html viewer, adds a brand new video player and brings some improvements for voice messages. Thanks to everyone involved! + +This release adds more functionality for spaces, enhances the html viewer, adds a brand new video +player and brings some improvements for voice messages. Thanks to everyone involved! ### All changes: @@ -1761,7 +1931,8 @@ This release adds more functionality for spaces, enhances the html viewer, adds - fix: Display loading dialog on start DM - fix: Dont add/remove DMs to space - fix: Empty timelines crashing the room view -- fix: excessive CPU usage on Windows, as described in https://github.com/flutter/flutter/issues/78517#issuecomment-846436695 +- fix: excessive CPU usage on Windows, as described + in https://github.com/flutter/flutter/issues/78517#issuecomment-846436695 - fix: Joining room aliases not published into the room directory - fix: Keep display alive while recording - fix: Load space members to display DM rooms @@ -1779,22 +1950,27 @@ This release adds more functionality for spaces, enhances the html viewer, adds - fix: Wrap login form into `AutofillGroup` ## v0.37.0 - 2021-08-06 + - Implement location sharing - Updated translations - Improved spaces support - Minor bug fixes ## v0.36.2 - 2021-08-03 + Hotfix a routing problem on web and desktop ## v0.36.1 - 2021-08-03 + - Hotfix uploading to many OTKs - Implement initial spaces UI ## v0.36.0 - 2021-07-31 + Minor design improvements and bug fixes. ### All changes: + * design: Make unread listtiles more visible * design: Move pinned icon in title * feat: Rate limit streams so that large accounts have a smoother UI @@ -1807,10 +1983,13 @@ Minor design improvements and bug fixes. * fix: Tests ## v0.35.0 - 2021-07-24 + This release introduces stickers and a lot of minor bug fixes and improvements. ### All changes: + ### Feature + * Add sticker picker [205d7e8] * Also suggest username completions based on their slugs [3d980df] * Nicer mentions [99bc819] @@ -1819,6 +1998,7 @@ This release introduces stickers and a lot of minor bug fixes and improvements. * Android SSO in webview [befd8e1] ### Fixes + * Reset bootstrap on bad ssss [b78b654] * Hide stickers button when there is not sticker pack [b71dd4b] * Download files on iOS [a8201c4] @@ -1834,15 +2014,19 @@ This release introduces stickers and a lot of minor bug fixes and improvements. * Close safariviewcontroller on SSO [ba685b7] ### Refactor + * Rename store and allow storing custom values [b1c35e5] ## v0.34.1 - 2021-07-14 + Bugfix image picker on Android 11 ## v0.34.0 - 2021-07-13 + Mostly bugfixes and one new feature: Lottie file rendering. ### All changes: + * feat: Add rendering of lottie files * fix: Check for jitsi server in well-known lookup also on login screen * fix: show thumbnails in timeline on desktop @@ -1854,21 +2038,27 @@ Mostly bugfixes and one new feature: Lottie file rendering. * fix: Don't allow backup of the android app ## v0.33.3 - 2021-07-11 + Another bugfixing release to solve some problems and republish the app on iOS. ### Changes + * Redesign SSO buttons * Update dependencies * Remove moor database (no migration from here possible) * fix: Keyboard hides imagePicker buttons on iOS ## v0.33.2 - 2021-06-29 + * Fix Linux Flatpak persistent storing of data ## v0.33.0 - 2021-06-26 -Just a more minor bugfixing release with some design changes in the settings, updated missing translations and for rebuilding the arm64 Linux Flatpak. + +Just a more minor bugfixing release with some design changes in the settings, updated missing +translations and for rebuilding the arm64 Linux Flatpak. ### Features + * redesigned settings * Updated translations - thanks to all translators * display progress bar in first sync @@ -1876,23 +2066,31 @@ Just a more minor bugfixing release with some design changes in the settings, up * update some dependencies ### Fixes + * Favicon on web * Database not storing files correctly * Linux builds for arm64 * a lot of minor bugs ## v0.32.2 - 2021-06-20 + * fix: Broken hive keys ## v0.32.1 - 2021-06-17 -* fix: Hive breaks if room IDs contain emojis (yes there are users with hacked synapses out there who needs this) -* feat: Also migrate inbound group sessions +* fix: Hive breaks if room IDs contain emojis (yes there are users with hacked synapses out there + who needs this) +* feat: Also migrate inbound group sessions ## v0.32.0 - 2021-06-16 -FluffyChat 0.32.0 targets improved stability and a new onboarding flow where single sign on is now the more prominent way to get new users into the app. This release also introduces a complete rewritten database under the hood based on the key value store Hive instead of sqlite. This should improve the overall stability and the performance of the web version. + +FluffyChat 0.32.0 targets improved stability and a new onboarding flow where single sign on is now +the more prominent way to get new users into the app. This release also introduces a complete +rewritten database under the hood based on the key value store Hive instead of sqlite. This should +improve the overall stability and the performance of the web version. ### Feat + * Long-press reactions to see who sent this * New login UI * Shift+Enter makes a new line on web and desktop @@ -1902,6 +2100,7 @@ FluffyChat 0.32.0 targets improved stability and a new onboarding flow where sin * Minor design tweaks ### Fixes + * Single sign on on iOS and web * Database corruptions * Minor fixes @@ -1909,26 +2108,31 @@ FluffyChat 0.32.0 targets improved stability and a new onboarding flow where sin ## v0.31.3 - 2021-05-28 ### Fixes + * Build Linux * Multiline keyboard on web and desktop ## v0.31.2 - 2021-05-28 ### Fixes + * Setting up push was broken ## v0.31.0 - 2021-05-26 ### Chore + * Format iOS stuff [584c873] * LibOlm has been updated to 3.2.3 ### Feature + * Cute animation for hiding the + button in inputbar [37c40a2] * Improved chat bubble design and splash animations [0b3734f] * Zoom page transition on Android and Fuchsia [e6c20dd] ### Fixes + * "Pick an image" button in emote settings doesn't do anything [e6be684] * Formatting and style [2540a6c] * Emoji picker [e1bd4e1] @@ -1942,9 +2146,11 @@ FluffyChat 0.32.0 targets improved stability and a new onboarding flow where sin * Send read markers [08dd2d7] ### Docs + * Update code style [3e7269d] ### Refactor + * Structure files in more directories [ebc598a] * Rename UI to Views [e44de26] * rename UI to View and MVC login page [cc113bb] @@ -1957,40 +2163,58 @@ FluffyChat 0.32.0 targets improved stability and a new onboarding flow where sin ## v0.30.2 - 2021-05-13 ### Feature + * Implement registration with email [19616f3] ### Fixes + * Android input after sending message [4488520] ### Changes + * Switch to tchncs.de as default homeserver ### Refactor + * UIA registering [48bf116] ## v0.30.1 - 2021-05-07 ### Chore + * Update translations ### Fixes + * Record audio on iOS [cd1e9ae] ## v0.30.0 - 2021-05-01 -In this release we have mostly focused on bugfixing and stability. We have switched to the new Flutter 2 framework and have done a lot of refactoring under the hood. The annoying freezing bug should now be fixed. Voice messages now have a new backend which should improve the sound quality and stability. There is now a more professional UI for editing aliases of a room. Users can now see a list of all aliases, add new aliases, delete them and mark one alias as the canonical (or main) alias. Some minor design changes and design fixes should improve the overall UX of the app exspecially on tablets. +In this release we have mostly focused on bugfixing and stability. We have switched to the new +Flutter 2 framework and have done a lot of refactoring under the hood. The annoying freezing bug +should now be fixed. Voice messages now have a new backend which should improve the sound quality +and stability. There is now a more professional UI for editing aliases of a room. Users can now see +a list of all aliases, add new aliases, delete them and mark one alias as the canonical (or main) +alias. Some minor design changes and design fixes should improve the overall UX of the app +exspecially on tablets. -Version 0.30.0 will be the first version with arm64 support. You can download binaries from the CI and we will try to publish it on Flathub. Together with the new Linux Desktop Notifications feature, this might be interesting for the Librem 5 or the PinePhone. Sadly I don't own one of these very interesting devices. If you have one, I would very like to see some screenshots of it! :-) +Version 0.30.0 will be the first version with arm64 support. You can download binaries from the CI +and we will try to publish it on Flathub. Together with the new Linux Desktop Notifications feature, +this might be interesting for the Librem 5 or the PinePhone. Sadly I don't own one of these very +interesting devices. If you have one, I would very like to see some screenshots of it! :-) ### Chore + * Update UP and automatically re-register UP on startup [aa3348e] ### Feature + * Desktop notifications on Linux Desktop [25e76f0] * Much better alias managing [642db67] * Archive with clean up [f366ab6] ### Fixes + * Lock screen [f8ba7bd] * Freeze bug [15c3178] * UserBottomSheet [dbb0464] @@ -2005,6 +2229,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Chat UI doesnt load [4f20ea4] ### Refactor + * Remove unused variable [b9f5c94] * Remove flutter_sound [334d4c0] * Switch to record package [2cf4f47] @@ -2035,9 +2260,11 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.29.1 - 2021-04-13 ### Chore + * Bump version [215f3c8] ### Fixes + * Save file [3f854d6] * Routing broken in chat details [f1166b2] * Tests [e75a5a0] @@ -2045,6 +2272,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * nogooglewarning [7619941] ### Refactor + * MVC archive [c2cbad7] * MVC sign up password view [fa0162a] * MVC sign up view [db19b37] @@ -2053,6 +2281,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.29.0 - 2021-04-09 ### Chore + * Clean up repo [ef7ccef] * Bump version [81a4c26] * Nicer FAB icon [3eeb9a9] @@ -2061,9 +2290,11 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Remove unused dependencies [c505c50] ### Feature + * Experimental support for room upgrades [a3af5a9] ### Fixes + * Room upgrade again [1d40705] * Better padding [c79562f] * Room upgrade [dac26dd] @@ -2087,9 +2318,11 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Select room version [2f5a73f] ### Docs + * Add code style [035ad96] ### Refactor + * Move app_config to /configs [8b9f4a4] * homeserver picker view [8e828d8] * widgets dir [c9ab69a] @@ -2097,12 +2330,15 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.28.1 - 2021-03-28 ### Chore + * Update version [518634a] ### Feature + * Implement new search view design [e42dd4b] ### Fixes + * Share on iOS [ea31991] * Permission to send video call [4de6d16] * Unread badge color [49d5f86] @@ -2113,11 +2349,13 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Set status missing [17a3311] ### Refactor + * push stuff [b6eaf5b] ## v0.28.0 - 2021-03-16 ### Chore + * Bump version [f8ee682] * Change push gateway url [078aefa] * Update file picker cross dependency [91c6912] @@ -2127,12 +2365,14 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Update famedlySdk [ec64cf6] ### Feature + * Cache and resend status message [c8a7031] * New experimental design [94aa9a3] * Better verification design [9bcd6b2] * Verify and block devices in devices list [8ebacfe] ### Fixes + * substring in reply key respects unicode runes [5695342] * Resend status message [05cd699] * Remove test push [a838d90] @@ -2174,10 +2414,12 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Use single-isolate push [949771d] ### Docs + * Update readme and contributing [449e46d] * Update Turkish translation for website [4a664eb] ### Refactor + * Update SDK and enable login with email and phone [864b665] * Migrate to flutter 2 [bb97b1b] * Switch to TextButton [55803d1] @@ -2185,6 +2427,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.27.0 - 2021-02-17 ### Chore + * Switch to experimental new hedwig [30a1fb0] * update sdk & remove selfSign [26f7cb3] * Update sdk [cde8a30] @@ -2192,6 +2435,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Change push gateway port [8f36140] ### Feature + * localize bootstrap [395e62e] * Add more bootstrap features [e4db84a] * Add some tooltipps [b9eb8d1] @@ -2206,6 +2450,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Implement autofillhints [41a2457] ### Fixes + * Website [080a909] * docs _site dir [875d652] * Bootstrap dialog [c72da0a] @@ -2242,29 +2487,35 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * iOS push [c01bdf7] ### Docs + * Fix qr-codes [c7f0a74] * grammar fixes [c4d569b] ### Refactor + * Theme colors [fe13778] * border radius [ddd10d1] ## v0.26.1 - 2021-01-26 ### Chore + * Update SDK [e9df6bf] * Bump version [d79b356] * Update dependencies [6159f99] ### Feature + * Add unified push as push provider [124a5ee] ### Fixes + * Link color [16d6623] ## v0.26.0 - 2021-01-25 ### Chore + * Redesign textfields [aef8090] * Simplify bootstrap [2df4a78] * Update audio player icons [3f14d5e] @@ -2280,6 +2531,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Use correct paths on new server [2f00007] ### Feature + * emoji working on desktop [c3feb65] * Implement sso [d1d470d] * Implement app lock [77ee2ef] @@ -2287,6 +2539,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Display version number in app [e1e60c4] ### Fixes + * Dark mode fixes [36746c8] * Dark theme [0bd0e58] * clean up iOS dir [6ae59a8] @@ -2320,6 +2573,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Readme [dda0925] ### Docs + * Make howtofork.md less misunderstandable [96de54a] * Add howtofork.md [f091469] * Mention emoji font [bb53714] @@ -2327,23 +2581,28 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Update fdroid button [ea7e20b] ### Refactor + * Theme and iOS stuff [189f65a] * Upgrade to latest flutter_sound_lite [2f7dece] ## v0.25.1 - 2021-01-17 ### Chore + * Bump version [c881424] ### Fixes + * Change size [83e2385] ### Refactor + * remove deprecated approute [be08de5] ## v0.25.0 - 2021-01-16 ### Chore + * Minor design improvements [d4dbe83] * Minor design tweaks [06581e2] * Bump version [7f51f7f] @@ -2351,6 +2610,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Better authwebview [d76df0a] ### Fixes + * Share files [d018a4b] * Typing update [9b5a3ca] * Status [d27dbe0] @@ -2373,9 +2633,11 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Minor apl bugs [05b9551] ### Docs + * Update fdroid logo [31d16a0] ### Refactor + * Use APL [cbcfa15] * Use Provider [880f9cc] * Use adaptive_theme [5d52c26] @@ -2383,29 +2645,35 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.24.3 - 2021-01-15 ### Chore + * Bump version [46c8386] * Update SDK [ba0726c] * Update fdroid domain [f130681] * Update dependencies [611e5e3] ### Feature + * Add Turkish translations for website [817c7dd] * Handle matrix: URIs as per MSC2312 [1da643f] ### Fixes + * Format [84b2ac9] * Push gateway url [ed2fbf7] ## v0.24.2 - 2021-01-08 ### Chore + * Update linux version [ef9369c] * Update SDK [4a006c9] ### Feature + * Regulate when thumbnails are animated as per MSC2705 [f5e11c2] ### Fixes + * Don't allow an empty ssss passphrase in key verification [3a0ce79] * reactions [92684da] * Reply fallback sometimes being stripped incorrectly [e9ec699] @@ -2413,11 +2681,13 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Properly handle url encoding in matrix.to URLs [baccd0a] ### Refactor + * Switch to loading dialog [e84bc25] ## v0.24.1 - 2020-12-24 ### Chore + * Update linux build [a91407f] * Add website to main repo [4df33a1] * Update dependencies [0d9f418] @@ -2427,11 +2697,13 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Update SDK [e802593] ### Feature + * Better invite search bar [3c4a29b] * Open alias in discover page [f0d1f5a] * Implement logger [714c7b4] ### Fixes + * auto-dep update [d9e8c5f] * Read receipts and filtered events [0ae36f0] * Don't re-render the lock icon nearly as often [00a56a7] @@ -2450,6 +2722,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.24.0 - 2020-12-18 ### Chore + * Update dependencies [550cb4a] * Update SDK [775a33b] * Update dependencies [644433c] @@ -2458,6 +2731,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Update dependencies [5af4eab] ### Feature + * Add languages to iOS [68a5efb] * Bring back config.json [b6a0d37] * Implement emojipicker for reactions [20b3157] @@ -2473,6 +2747,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Implement rich notification settings [87a73dd] ### Fixes + * Update typing [3d70b1e] * Build in dev [f892a9f] * Fix that damn regex [8961bff] @@ -2489,16 +2764,19 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * CI [da5bc56] ### Refactor + * Update sdk [32acc21] ## v0.23.1 - 2020-11-25 ### Fixes + * Release CI [14d8c80] ## v0.23.0 - 2020-11-25 ### Chore + * Update adaptive dialogs [0061660] * Prettier redacted events [d1e291e] * Minor design changes in user viewer [b4fb283] @@ -2507,6 +2785,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Only load google services if needed [bae779a] ### Feature + * Next version [1af048e] * Annoy user with dialog to add a recovery method [d9ec9f6] * Implement password recovery [4b2fef5] @@ -2515,6 +2794,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Improved encryption UI [2516848] ### Fixes + * Broken dialog [97bb692] * set email dialog [72e325a] * Minor fixes [11e2dd5] @@ -2530,17 +2810,20 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Suggest correct rooms [59ec9de] ### Refactor + * Make verification in dialogs [1f9e953] * matrix to link prefix [1aa9c08] ## v0.22.1 - 2020-11-21 ### Fixes + * Input bar not working, making app unusable [10773b4] ## v0.22.0 - 2020-11-21 ### Chore + * fix CI [00ed0d6] * fix CI [bb4bb9f] * Fix CI variables [d3822b0] @@ -2554,6 +2837,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Remove unused dependency [d12de2d] ### Feature + * Add svg support and better image handling [f70bbc3] * add config.json [4b7fb6b] * persistent upload of release artifacts [1b2481b] @@ -2561,28 +2845,33 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Better encryption / verification [1ff986e] ### Fixes + * iOS [26731ab] * resolve some sentry issues [61f35e8] * resolve some sentry issues [2c3693e] * iOS build [9fee409] * Automatic update deps job [255c05d] -* Don't re-render message widgets on insertion of new messages, making e.g. audio playing not stop [25b2997] +* Don't re-render message widgets on insertion of new messages, making e.g. audio playing not + stop [25b2997] * Add missing safearea [caab868] * no pushers enpdoint [b3942ad] * Sentry and small null fix [5dc22be] ### Refactor + * CI [34d7fdd] * SDK update [7e23280] ## v0.21.1 - 2020-10-28 ### Chore + * update version code [d1dfa9c] ## v0.21.0 - 2020-10-28 ### Chore + * Change compileSdkVersion again [f93f9c2] * Update packages [b471bd0] * Update SDK [86a385d] @@ -2593,6 +2882,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * release [844b4a8] ### Fixes + * CompileSDKVersion [bcf75fc] * Target sdk [c3e23b6] * File picker issue [aa191c1] @@ -2608,6 +2898,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.20.0 - 2020-10-23 ### Chore + * update dependencies [427cdc0] * upate matrix link text [0892ca9] * Change default linux window size [719323a] @@ -2619,6 +2910,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Make app ready for flutter 1 22 [e5b23fa] ### Feature + * Implement mouse select chat list items [6d41136] * Implement linux desktop notifications [75cd6f1] * Implement change device name [bfd3888] @@ -2631,6 +2923,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Enable macOS build [a845209] ### Fixes + * return text field to the previous state after editing message [08e61c0] * Web server picker [4cb19be] * Some single-emoji names crashing [b29ebce] @@ -2673,6 +2966,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi ## v0.19.0 - 2020-09-21 ### Chore + * Version update & olm-CI [0f805a2] * Update SDK & Changelog [1825543] * Add new language [c6d67ad] @@ -2686,6 +2980,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * update sdk [954eedb] ### Feature + * Implement send reactions [6bf25b7] * Improve design [c8a63c6] * Display emotes/emojis bigger [9cccd07] @@ -2701,6 +2996,7 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * New notification sound [8a5be21] ### Fixes + * Last bits for the release [1db9bdd] * Small stuff [9d3f272] * Search bar [eca25de] @@ -2716,5 +3012,5 @@ Version 0.30.0 will be the first version with arm64 support. You can download bi * Send read receipt only on focus [98316f1] * Desktop notifications [b05bfa6] - -This CHANGELOG.md was generated with [**Changelog for Dart**](https://pub.dartlang.org/packages/changelog) +This CHANGELOG.md was generated with [**Changelog for Dart +**](https://pub.dartlang.org/packages/changelog) diff --git a/pubspec.yaml b/pubspec.yaml index 41ef7014a..880229abf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: fluffychat description: Chat with your friends. publish_to: none # On version bump also increase the build number for F-Droid -version: 1.25.0+3537 +version: 1.26.0+3538 environment: sdk: ">=3.0.0 <4.0.0"