From 1f37cd4ebe22c74450444b655acf271d55688d29 Mon Sep 17 00:00:00 2001 From: krida2000 Date: Thu, 6 Apr 2023 13:01:20 +0300 Subject: [PATCH 01/26] Transfer changes from `new-design-preview` --- assets/l10n/en-US.ftl | 4 + assets/l10n/ru-RU.ftl | 4 + lib/domain/model/application_settings.dart | 5 + lib/domain/repository/settings.dart | 3 + lib/provider/hive/application_settings.dart | 7 + lib/routes.dart | 1 + lib/store/settings.dart | 4 + lib/ui/page/home/page/chat/view.dart | 66 ++-- .../home/page/chat/widget/chat_forward.dart | 167 +++++--- .../page/home/page/chat/widget/chat_item.dart | 372 ++++++++++++------ .../timeline_switch/controller.dart | 41 ++ .../page/my_profile/timeline_switch/view.dart | 142 +++++++ lib/ui/page/home/page/my_profile/view.dart | 47 +++ lib/ui/page/home/tab/menu/view.dart | 8 + 14 files changed, 667 insertions(+), 204 deletions(-) create mode 100644 lib/ui/page/home/page/my_profile/timeline_switch/controller.dart create mode 100644 lib/ui/page/home/page/my_profile/timeline_switch/view.dart diff --git a/assets/l10n/en-US.ftl b/assets/l10n/en-US.ftl index b40a339f4d7..ff6bae41880 100644 --- a/assets/l10n/en-US.ftl +++ b/assets/l10n/en-US.ftl @@ -431,6 +431,7 @@ label_chat_members = Members label_chat_monolog = Saved messages label_chats = Messages label_clear_history = Clear history +label_compact_timeline = As timeline label_confirm = Confirm label_confirmation_code = Confirmation code label_contact = Contact @@ -455,6 +456,7 @@ label_delete_for_me = Delete for me label_delete_message = Delete the message? label_delete_phone_number = Delete phone number label_delivered = Delivered +label_detailed_timeline = In message label_details = Details. label_dialog_created = Dialog created label_direct_chat_link = Direct chat link @@ -554,6 +556,7 @@ label_media_settings = Media settings label_menu = Menu label_message = Message label_message_will_deleted_for_you = The message will be deleted only for you. +label_messages_displaying = Timeline style label_mute_for = { $days -> [0] { $hours -> [0] { $minutes -> @@ -671,6 +674,7 @@ label_subtitle_participants = participants label_tab_chats = Chats label_tab_contacts = Contacts label_tab_menu = Menu +label_timeline_displaying = Display time stamps label_transition_count = Transitions: {$count} label_typing = Typing label_unconfirmed = Unconfirmed diff --git a/assets/l10n/ru-RU.ftl b/assets/l10n/ru-RU.ftl index cecb4406d7f..c9058b3a79b 100644 --- a/assets/l10n/ru-RU.ftl +++ b/assets/l10n/ru-RU.ftl @@ -446,6 +446,7 @@ label_chat_members = Участники label_chat_monolog = Сохранённые сообщения label_chats = Чаты label_clear_history = Очистить историю +label_compact_timeline = Как таймлайн label_confirm = Подтвердить label_confirmation_code = Код подтверждения label_contact = Контакт @@ -470,6 +471,7 @@ label_delete_for_me = Удалить для меня label_delete_message = Удалить сообщение? label_delete_phone_number = Удалить номер телефона label_delivered = Доставлено +label_detailed_timeline = В сообщении label_details = Подробнее. label_dialog_created = Диалог создан label_direct_chat_link = Прямая ссылка на чат @@ -570,6 +572,7 @@ label_media_settings = Настройки медиа label_menu = Меню label_message = Сообщение label_message_will_deleted_for_you = Сообщение будет удалено только для Вас. +label_messages_displaying = Стиль метки времени label_mute_for = { $days -> [0] { $hours -> [0] { $minutes -> @@ -691,6 +694,7 @@ label_subtitle_participants = участников label_tab_chats = Чаты label_tab_contacts = Контакты label_tab_menu = Меню +label_timeline_displaying = Отображать метки времени label_transition_count = Переходов: {$count} label_typing = Печатает label_unconfirmed = Неподтвержденный diff --git a/lib/domain/model/application_settings.dart b/lib/domain/model/application_settings.dart index 5bf55495489..0888e04cc62 100644 --- a/lib/domain/model/application_settings.dart +++ b/lib/domain/model/application_settings.dart @@ -34,6 +34,7 @@ class ApplicationSettings extends HiveObject { this.showDragAndDropButtonsHint = false, this.sortContactsByName = true, this.loadImages = true, + this.timelineEnabled = true, }); /// Indicator whether [OngoingCall]s are preferred to be displayed in the @@ -75,4 +76,8 @@ class ApplicationSettings extends HiveObject { /// Indicator whether [ImageAttachment]s should be loaded automatically. @HiveField(8) bool loadImages; + + /// Indicator whether time should be displayed in timeline mode in chat. + @HiveField(9) + bool timelineEnabled; } diff --git a/lib/domain/repository/settings.dart b/lib/domain/repository/settings.dart index 200cde4387e..c8492f798df 100644 --- a/lib/domain/repository/settings.dart +++ b/lib/domain/repository/settings.dart @@ -84,4 +84,7 @@ abstract class AbstractSettingsRepository { /// Returns the [Rect] preferences of an [OngoingCall] happening in the /// specified [Chat]. Rect? getCallRect(ChatId id); + + /// Sets the [ApplicationSettings.timelineEnabled] value. + Future setTimelineEnabled(bool enabled); } diff --git a/lib/provider/hive/application_settings.dart b/lib/provider/hive/application_settings.dart index 11e64ffd108..789e8366f03 100644 --- a/lib/provider/hive/application_settings.dart +++ b/lib/provider/hive/application_settings.dart @@ -92,4 +92,11 @@ class ApplicationSettingsHiveProvider 0, (box.get(0) ?? ApplicationSettings())..loadImages = enabled, ); + + /// Stores a new [enabled] value of [ApplicationSettings.timelineEnabled] + /// to [Hive]. + Future setTimelineEnabled(bool enabled) => putSafe( + 0, + (box.get(0) ?? ApplicationSettings())..timelineEnabled = enabled, + ); } diff --git a/lib/routes.dart b/lib/routes.dart index 13036c076a0..34d055bb95f 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -100,6 +100,7 @@ enum ProfileTab { signing, link, background, + chats, calls, media, notifications, diff --git a/lib/store/settings.dart b/lib/store/settings.dart index 649e59ad850..7f046a9f196 100644 --- a/lib/store/settings.dart +++ b/lib/store/settings.dart @@ -150,6 +150,10 @@ class SettingsRepository extends DisposableInterface @override Rect? getCallRect(ChatId id) => _callRectLocal.get(id); + @override + Future setTimelineEnabled(bool enabled) => + _settingsLocal.setTimelineEnabled(enabled); + /// Initializes [MediaSettingsHiveProvider.boxEvents] subscription. Future _initMediaSubscription() async { _mediaSubscription = StreamIterator(_mediaLocal.boxEvents); diff --git a/lib/ui/page/home/page/chat/view.dart b/lib/ui/page/home/page/chat/view.dart index 853c613ac70..6b5fb2e2b69 100644 --- a/lib/ui/page/home/page/chat/view.dart +++ b/lib/ui/page/home/page/chat/view.dart @@ -269,7 +269,8 @@ class _ChatViewState extends State ), body: Listener( onPointerSignal: (s) { - if (s is PointerScrollEvent) { + if (s is PointerScrollEvent && + c.settings.value?.timelineEnabled == true) { if ((s.scrollDelta.dy.abs() < 3 && s.scrollDelta.dx.abs() > 3) || c.isHorizontalScroll.value) { @@ -317,38 +318,40 @@ class _ChatViewState extends State AllowMultipleHorizontalDragGestureRecognizer(), (AllowMultipleHorizontalDragGestureRecognizer instance) { - instance.onUpdate = (d) { - if (!c.isItemDragged.value && - c.scrollOffset.dy.abs() < 7 && - c.scrollOffset.dx.abs() > 7 && - c.isSelecting.isFalse) { - double value = - (_animation.value - d.delta.dx / 100) - .clamp(0, 1); - - if (_animation.value != 1 && value == 1 || - _animation.value != 0 && value == 0) { - HapticFeedback.selectionClick(); + if (c.settings.value?.timelineEnabled == true) { + instance.onUpdate = (d) { + if (!c.isItemDragged.value && + c.scrollOffset.dy.abs() < 7 && + c.scrollOffset.dx.abs() > 7 && + c.isSelecting.isFalse) { + double value = + (_animation.value - d.delta.dx / 100) + .clamp(0, 1); + + if (_animation.value != 1 && value == 1 || + _animation.value != 0 && value == 0) { + HapticFeedback.selectionClick(); + } + + _animation.value = value.clamp(0, 1); } - - _animation.value = value.clamp(0, 1); - } - }; - - instance.onEnd = (d) async { - c.scrollOffset = Offset.zero; - if (!c.isItemDragged.value && - _animation.value != 1 && - _animation.value != 0) { - if (_animation.value >= 0.5) { - await _animation.forward(); - HapticFeedback.selectionClick(); - } else { - await _animation.reverse(); - HapticFeedback.selectionClick(); + }; + + instance.onEnd = (d) async { + c.scrollOffset = Offset.zero; + if (!c.isItemDragged.value && + _animation.value != 1 && + _animation.value != 0) { + if (_animation.value >= 0.5) { + await _animation.forward(); + HapticFeedback.selectionClick(); + } else { + await _animation.reverse(); + HapticFeedback.selectionClick(); + } } - } - }; + }; + } }, ) }, @@ -599,6 +602,7 @@ class _ChatViewState extends State user: u.data, getUser: c.getUser, animation: _animation, + displayTime: c.settings.value?.timelineEnabled != true, onHide: () => c.hideChatItem(e.value), onDelete: () => c.deleteMessage(e.value), onReply: () { diff --git a/lib/ui/page/home/page/chat/widget/chat_forward.dart b/lib/ui/page/home/page/chat/widget/chat_forward.dart index 8c17541a6cd..f6e53079581 100644 --- a/lib/ui/page/home/page/chat/widget/chat_forward.dart +++ b/lib/ui/page/home/page/chat/widget/chat_forward.dart @@ -281,7 +281,11 @@ class _ChatForwardWidgetState extends State { ? const Radius.circular(15) : Radius.zero, ), - child: _forwardedMessage(e, menu), + child: _forwardedMessage( + e, + menu, + showTimeline: i == widget.forwards.length - 1, + ), ), ), ], @@ -297,7 +301,11 @@ class _ChatForwardWidgetState extends State { } /// Returns a visual representation of the provided [forward]. - Widget _forwardedMessage(Rx forward, bool menu) { + Widget _forwardedMessage( + Rx forward, + bool menu, { + bool showTimeline = false, + }) { return Obx(() { ChatForward msg = forward.value as ChatForward; ChatItemQuote quote = msg.quote; @@ -476,61 +484,72 @@ class _ChatForwardWidgetState extends State { (snapshot.data?.user.value.num.val.sum() ?? 3) % AvatarWidget.colors.length]; - return Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + return Column( + crossAxisAlignment: CrossAxisAlignment.end, children: [ - const SizedBox(width: 12), - Flexible( - child: Container( - decoration: BoxDecoration( - border: Border( - left: BorderSide(width: 2, color: color), - ), - ), - margin: const EdgeInsets.fromLTRB(0, 8, 12, 8), - padding: const EdgeInsets.only(left: 8), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(width: 12), + Flexible( + child: Container( + decoration: BoxDecoration( + border: Border( + left: BorderSide(width: 2, color: color), + ), + ), + margin: const EdgeInsets.fromLTRB(0, 8, 12, 8), + padding: const EdgeInsets.only(left: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Transform.scale( - scaleX: -1, - child: - Icon(Icons.reply, size: 17, color: color), + Row( + children: [ + Transform.scale( + scaleX: -1, + child: Icon(Icons.reply, + size: 17, color: color), + ), + const SizedBox(width: 6), + Flexible( + child: Text( + snapshot.data?.user.value.name?.val ?? + snapshot.data?.user.value.num.val ?? + 'dot'.l10n * 3, + style: style.boldBody + .copyWith(color: color), + ), + ), + ], ), - const SizedBox(width: 6), - Flexible( - child: Text( - snapshot.data?.user.value.name?.val ?? - snapshot.data?.user.value.num.val ?? - 'dot'.l10n * 3, - style: - style.boldBody.copyWith(color: color), + if (content != null) ...[ + const SizedBox(height: 2), + content, + ], + if (additional.isNotEmpty) ...[ + const SizedBox(height: 4), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + msg.authorId == widget.me + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: additional, ), - ), + ], ], ), - if (content != null) ...[ - const SizedBox(height: 2), - content, - ], - if (additional.isNotEmpty) ...[ - const SizedBox(height: 4), - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: msg.authorId == widget.me - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: additional, - ), - ], - ], - ), + ), + ) + ], + ), + if (showTimeline) + Padding( + padding: const EdgeInsets.only(right: 8, bottom: 4), + child: _timeline(forward.value), ), - ) ], ); }, @@ -1030,6 +1049,54 @@ class _ChatForwardWidgetState extends State { ); } + /// Return timeline label for the provided item. + Widget _timeline(ChatItem item) { + final Style style = Theme.of(context).extension