From b449735bf5be779d46ec6f39cb83907aca067b7e Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 13 Sep 2024 20:22:10 +0800 Subject: [PATCH] :sparkles: Better side navigation :bug: Bug fixes and optimizations --- assets/locales/en_us.json | 3 +- assets/locales/zh_cn.json | 3 +- lib/controllers/post_editor_controller.dart | 15 +-- lib/main.dart | 4 +- lib/providers/theme_switcher.dart | 4 +- lib/router.dart | 1 + lib/screens/account/friend.dart | 2 +- lib/screens/account/profile_page.dart | 4 +- lib/screens/channel/call/call.dart | 2 +- lib/screens/channel/channel_chat.dart | 10 +- lib/screens/channel/channel_organize.dart | 2 +- lib/screens/chat.dart | 4 +- lib/screens/dashboard.dart | 2 +- lib/screens/feed.dart | 8 +- lib/screens/feed/draft_box.dart | 4 +- lib/screens/posts/post_editor.dart | 42 ++++--- lib/screens/realms.dart | 4 +- lib/screens/realms/realm_organize.dart | 2 +- lib/screens/realms/realm_view.dart | 2 +- lib/screens/settings.dart | 4 +- lib/shells/centered_shell.dart | 2 +- lib/shells/root_shell.dart | 4 +- lib/shells/sidebar_shell.dart | 8 +- lib/shells/title_shell.dart | 4 +- lib/theme.dart | 8 +- lib/widgets/app_bar_title.dart | 2 +- .../channel/channel_call_indicator.dart | 4 +- lib/widgets/channel/channel_list.dart | 64 +++++++--- lib/widgets/chat/chat_event.dart | 8 +- lib/widgets/chat/chat_message_input.dart | 3 +- .../navigation/app_navigation_drawer.dart | 34 +++--- .../navigation/app_navigation_region.dart | 114 ++++++++---------- lib/widgets/posts/post_item.dart | 17 ++- 33 files changed, 212 insertions(+), 182 deletions(-) diff --git a/assets/locales/en_us.json b/assets/locales/en_us.json index 32d9dd2..e810157 100644 --- a/assets/locales/en_us.json +++ b/assets/locales/en_us.json @@ -391,5 +391,6 @@ "userLevel10": "Grandmaster", "userLevel11": "Legend", "userLevel12": "Mythic", - "userLevel13": "Immortal" + "userLevel13": "Immortal", + "postBrowsingIn": "Browsing in @region" } diff --git a/assets/locales/zh_cn.json b/assets/locales/zh_cn.json index 237b145..4c1a0ba 100644 --- a/assets/locales/zh_cn.json +++ b/assets/locales/zh_cn.json @@ -392,5 +392,6 @@ "userLevel10": "出神入化", "userLevel11": "名垂千古", "userLevel12": "独占鳌头", - "userLevel13": "万古流芳" + "userLevel13": "万古流芳", + "postBrowsingIn": "浏览 @region 内的帖子中" } diff --git a/lib/controllers/post_editor_controller.dart b/lib/controllers/post_editor_controller.dart index a4f6cda..c8acbef 100644 --- a/lib/controllers/post_editor_controller.dart +++ b/lib/controllers/post_editor_controller.dart @@ -155,13 +155,14 @@ class PostEditorController extends GetxController { ); } - void localRead() { - SharedPreferences.getInstance().then((inst) { - if (inst.containsKey('post_editor_local_save')) { - isRestoreFromLocal.value = true; - payload = jsonDecode(inst.getString('post_editor_local_save')!); - } - }); + Future localRead() async { + final inst = await SharedPreferences.getInstance(); + if (inst.containsKey('post_editor_local_save')) { + isRestoreFromLocal.value = true; + payload = jsonDecode(inst.getString('post_editor_local_save')!); + return true; + } + return false; } void localClear() { diff --git a/lib/main.dart b/lib/main.dart index 2d70d2b..9263d4c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,8 +80,8 @@ Future _initializePlatformComponents() async { } final themeSwitcher = ThemeSwitcher( - lightThemeData: SolianTheme.build(Brightness.light), - darkThemeData: SolianTheme.build(Brightness.dark), + lightThemeData: AppTheme.build(Brightness.light), + darkThemeData: AppTheme.build(Brightness.dark), ); class SolianApp extends StatelessWidget { diff --git a/lib/providers/theme_switcher.dart b/lib/providers/theme_switcher.dart index c1e158b..acc1b71 100644 --- a/lib/providers/theme_switcher.dart +++ b/lib/providers/theme_switcher.dart @@ -16,8 +16,8 @@ class ThemeSwitcher extends ChangeNotifier { if (prefs.containsKey('global_theme_color')) { final value = prefs.getInt('global_theme_color')!; final color = Color(value); - lightThemeData = SolianTheme.build(Brightness.light, seedColor: color); - darkThemeData = SolianTheme.build(Brightness.dark, seedColor: color); + lightThemeData = AppTheme.build(Brightness.light, seedColor: color); + darkThemeData = AppTheme.build(Brightness.dark, seedColor: color); notifyListeners(); } } diff --git a/lib/router.dart b/lib/router.dart index 790ff83..5ebba55 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -154,6 +154,7 @@ abstract class AppRouter { name: 'channelChat', builder: (context, state) { return ChannelChatScreen( + key: UniqueKey(), alias: state.pathParameters['alias']!, realm: state.uri.queryParameters['realm'] ?? 'global', ); diff --git a/lib/screens/account/friend.dart b/lib/screens/account/friend.dart index ad9bf3e..d878aa3 100644 --- a/lib/screens/account/friend.dart +++ b/lib/screens/account/friend.dart @@ -133,7 +133,7 @@ class _FriendScreenState extends State ).paddingAll(14), ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], bottom: TabBar( diff --git a/lib/screens/account/profile_page.dart b/lib/screens/account/profile_page.dart index 80735ed..d058649 100644 --- a/lib/screens/account/profile_page.dart +++ b/lib/screens/account/profile_page.dart @@ -152,7 +152,7 @@ class _AccountProfilePageState extends State { SliverAppBar( centerTitle: false, floating: true, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), leadingWidth: 24, automaticallyImplyLeading: false, flexibleSpace: Row( @@ -207,7 +207,7 @@ class _AccountProfilePageState extends State { onPressed: null, ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ), diff --git a/lib/screens/channel/call/call.dart b/lib/screens/channel/call/call.dart index 9074ca6..7bf6963 100644 --- a/lib/screens/channel/call/call.dart +++ b/lib/screens/channel/call/call.dart @@ -205,7 +205,7 @@ class _CallScreenState extends State with TickerProviderStateMixin { : AppBar( leading: AppBarLeadingButton.adaptive(context), centerTitle: true, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), title: Obx( () => RichText( textAlign: TextAlign.center, diff --git a/lib/screens/channel/channel_chat.dart b/lib/screens/channel/channel_chat.dart index 67cdcfe..1aec854 100644 --- a/lib/screens/channel/channel_chat.dart +++ b/lib/screens/channel/channel_chat.dart @@ -217,8 +217,8 @@ class _ChannelChatScreenState extends State leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle(title), centerTitle: false, - titleSpacing: SolianTheme.titleSpacing(context), - toolbarHeight: SolianTheme.toolbarHeight(context), + titleSpacing: AppTheme.titleSpacing(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ const BackgroundStateWidget(), Builder(builder: (context) { @@ -255,7 +255,7 @@ class _ChannelChatScreenState extends State }, ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ), @@ -276,7 +276,7 @@ class _ChannelChatScreenState extends State channel: _channel!, ongoingCall: _ongoingCall!, onJoin: () { - if (!SolianTheme.isLargeScreen(context)) { + if (!AppTheme.isLargeScreen(context)) { final ChatCallProvider call = Get.find(); call.gotoScreen(context); } @@ -337,7 +337,7 @@ class _ChannelChatScreenState extends State ), Obx(() { final ChatCallProvider call = Get.find(); - if (call.isMounted.value && SolianTheme.isLargeScreen(context)) { + if (call.isMounted.value && AppTheme.isLargeScreen(context)) { return const Expanded( child: Row(children: [ VerticalDivider(width: 0.3, thickness: 0.3), diff --git a/lib/screens/channel/channel_organize.dart b/lib/screens/channel/channel_organize.dart index 386cab7..d0c7a26 100644 --- a/lib/screens/channel/channel_organize.dart +++ b/lib/screens/channel/channel_organize.dart @@ -110,7 +110,7 @@ class _ChannelOrganizeScreenState extends State { appBar: AppBar( title: AppBarTitle('channelOrganizing'.tr), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ TextButton( onPressed: _isBusy ? null : () => applyChannel(), diff --git a/lib/screens/chat.dart b/lib/screens/chat.dart index bcdb481..ad7b94a 100644 --- a/lib/screens/chat.dart +++ b/lib/screens/chat.dart @@ -47,7 +47,7 @@ class _ChatScreenState extends State { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle('chat'.tr), centerTitle: true, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ const BackgroundStateWidget(), const NotificationButton(), @@ -95,7 +95,7 @@ class _ChatScreenState extends State { ], ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ), diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index e3264b8..6be76c5 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -504,7 +504,7 @@ class _DashboardScreenState extends State { /// Footer Column( - mainAxisAlignment: SolianTheme.isLargeScreen(context) + mainAxisAlignment: AppTheme.isLargeScreen(context) ? MainAxisAlignment.start : MainAxisAlignment.center, children: [ diff --git a/lib/screens/feed.dart b/lib/screens/feed.dart index a868fbe..4479844 100644 --- a/lib/screens/feed.dart +++ b/lib/screens/feed.dart @@ -85,13 +85,13 @@ class _FeedScreenState extends State title: AppBarTitle('feed'.tr), centerTitle: false, floating: true, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), leading: AppBarLeadingButton.adaptive(context), actions: [ const BackgroundStateWidget(), const NotificationButton(), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], bottom: TabBar( @@ -118,7 +118,9 @@ class _FeedScreenState extends State MaterialBanner( leading: const Icon(Icons.layers), content: Text( - 'Browsing in realm #${navState.focusedRealm.value!.alias}', + 'postBrowsingIn'.trParams({ + 'region': '#${navState.focusedRealm.value!.alias}', + }), ), actions: const [SizedBox.shrink()], ), diff --git a/lib/screens/feed/draft_box.dart b/lib/screens/feed/draft_box.dart index 1b74536..762655f 100644 --- a/lib/screens/feed/draft_box.dart +++ b/lib/screens/feed/draft_box.dart @@ -61,10 +61,10 @@ class _DraftBoxScreenState extends State { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle('draftBox'.tr), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ), diff --git a/lib/screens/posts/post_editor.dart b/lib/screens/posts/post_editor.dart index 60f759e..dc9ce5d 100644 --- a/lib/screens/posts/post_editor.dart +++ b/lib/screens/posts/post_editor.dart @@ -11,6 +11,7 @@ import 'package:solian/models/post.dart'; import 'package:solian/models/realm.dart'; import 'package:solian/providers/attachment_uploader.dart'; import 'package:solian/providers/auth.dart'; +import 'package:solian/providers/navigation.dart'; import 'package:solian/router.dart'; import 'package:solian/theme.dart'; import 'package:solian/widgets/app_bar_leading.dart'; @@ -124,7 +125,12 @@ class _PostPublishScreenState extends State { void initState() { super.initState(); if (widget.edit == null && widget.reply == null && widget.repost == null) { - _editorController.localRead(); + _editorController.localRead().then((res) { + if (!res) { + final navState = Get.find(); + _editorController.realmZone.value = navState.focusedRealm.value; + } + }); } if (widget.reply != null) { _editorController.replyTo.value = widget.reply; @@ -158,7 +164,7 @@ class _PostPublishScreenState extends State { ), ), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ TextButton( onPressed: _isBusy ? null : () => _applyPost(), @@ -177,23 +183,19 @@ class _PostPublishScreenState extends State { children: [ ListTile( tileColor: Theme.of(context).colorScheme.surfaceContainerLow, - title: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Text( - _editorController.title ?? 'title'.tr, - maxLines: 1, - overflow: TextOverflow.ellipsis, + title: Row( + children: [ + Text( + _editorController.title ?? 'title'.tr, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const Gap(6), + if (_editorController.aliasController.text.isNotEmpty) + Badge( + label: Text('#${_editorController.aliasController.text}'), ), - const Gap(6), - if (_editorController.aliasController.text.isNotEmpty) - Badge( - label: - Text('#${_editorController.aliasController.text}'), - ), - ], - ), + ], ), subtitle: Text( _editorController.description ?? 'description'.tr, @@ -365,12 +367,12 @@ class _PostPublishScreenState extends State { ], ), ), - if (SolianTheme.isLargeScreen(context)) + if (AppTheme.isLargeScreen(context)) const VerticalDivider(width: 0.3, thickness: 0.3) .paddingSymmetric( horizontal: 16, ), - if (SolianTheme.isLargeScreen(context)) + if (AppTheme.isLargeScreen(context)) Expanded( child: SingleChildScrollView( child: MarkdownTextContent( diff --git a/lib/screens/realms.dart b/lib/screens/realms.dart index 68bad72..51e2500 100644 --- a/lib/screens/realms.dart +++ b/lib/screens/realms.dart @@ -62,7 +62,7 @@ class _RealmListScreenState extends State { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle('realm'.tr), centerTitle: true, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ const BackgroundStateWidget(), const NotificationButton(), @@ -77,7 +77,7 @@ class _RealmListScreenState extends State { }, ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ), diff --git a/lib/screens/realms/realm_organize.dart b/lib/screens/realms/realm_organize.dart index 4e7a98d..89acd26 100644 --- a/lib/screens/realms/realm_organize.dart +++ b/lib/screens/realms/realm_organize.dart @@ -102,7 +102,7 @@ class _RealmOrganizeScreenState extends State { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle('realmOrganizing'.tr), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ TextButton( onPressed: _isBusy ? null : () => applyRealm(), diff --git a/lib/screens/realms/realm_view.dart b/lib/screens/realms/realm_view.dart index f83634d..991ef34 100644 --- a/lib/screens/realms/realm_view.dart +++ b/lib/screens/realms/realm_view.dart @@ -114,7 +114,7 @@ class _RealmViewScreenState extends State { }, ), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], bottom: const TabBar( diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index e1be04c..0f04bfa 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -33,11 +33,11 @@ class _SettingScreenState extends State { tooltip: label, onPressed: () { context.read().setTheme( - SolianTheme.build( + AppTheme.build( Brightness.light, seedColor: color, ), - SolianTheme.build( + AppTheme.build( Brightness.dark, seedColor: color, ), diff --git a/lib/shells/centered_shell.dart b/lib/shells/centered_shell.dart index fbfa20e..1c2cdeb 100644 --- a/lib/shells/centered_shell.dart +++ b/lib/shells/centered_shell.dart @@ -25,7 +25,7 @@ class CenteredShell extends StatelessWidget { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), ) : null, body: Center( diff --git a/lib/shells/root_shell.dart b/lib/shells/root_shell.dart index c66c981..3652301 100644 --- a/lib/shells/root_shell.dart +++ b/lib/shells/root_shell.dart @@ -41,10 +41,10 @@ class RootShell extends StatelessWidget { return Scaffold( key: rootScaffoldKey, - drawer: SolianTheme.isLargeScreen(context) + drawer: AppTheme.isLargeScreen(context) ? null : AppNavigationDrawer(routeName: routeName), - body: SolianTheme.isLargeScreen(context) + body: AppTheme.isLargeScreen(context) ? Row( children: [ if (showNavigation) AppNavigationDrawer(routeName: routeName), diff --git a/lib/shells/sidebar_shell.dart b/lib/shells/sidebar_shell.dart index 866aeb0..af6a7ca 100644 --- a/lib/shells/sidebar_shell.dart +++ b/lib/shells/sidebar_shell.dart @@ -29,9 +29,9 @@ class SidebarShell extends StatelessWidget { flex: 2, child: child, ), - if (SolianTheme.isExtraLargeScreen(context)) + if (AppTheme.isExtraLargeScreen(context)) const VerticalDivider(thickness: 0.3, width: 1), - if (SolianTheme.isExtraLargeScreen(context)) + if (AppTheme.isExtraLargeScreen(context)) Flexible( flex: 1, child: sidebar ?? const SidebarPlaceholder(), @@ -47,10 +47,10 @@ class SidebarShell extends StatelessWidget { leading: AppBarLeadingButton.adaptive(context), title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr), centerTitle: false, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), ) : null, - body: SolianTheme.isLargeScreen(context) + body: AppTheme.isLargeScreen(context) ? Row( children: sidebarFirst ? buildContent(context).reversed.toList() diff --git a/lib/shells/title_shell.dart b/lib/shells/title_shell.dart index 1fa6820..3fabdc9 100644 --- a/lib/shells/title_shell.dart +++ b/lib/shells/title_shell.dart @@ -32,11 +32,11 @@ class TitleShell extends StatelessWidget { title ?? (state!.topRoute?.name?.tr ?? 'page'.tr), ), centerTitle: isCenteredTitle, - toolbarHeight: SolianTheme.toolbarHeight(context), + toolbarHeight: AppTheme.toolbarHeight(context), actions: [ const BackgroundStateWidget(), SizedBox( - width: SolianTheme.isLargeScreen(context) ? 8 : 16, + width: AppTheme.isLargeScreen(context) ? 8 : 16, ), ], ) diff --git a/lib/theme.dart b/lib/theme.dart index 3a70764..dd12e72 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:solian/platform.dart'; -abstract class SolianTheme { +abstract class AppTheme { static bool isLargeScreen(BuildContext context) => MediaQuery.of(context).size.width > 640; @@ -9,13 +9,13 @@ abstract class SolianTheme { MediaQuery.of(context).size.width > 720; static bool isSpecializedMacOS(BuildContext context) => - PlatformInfo.isMacOS && !SolianTheme.isLargeScreen(context); + PlatformInfo.isMacOS && !AppTheme.isLargeScreen(context); static double? titleSpacing(BuildContext context) { - if (SolianTheme.isSpecializedMacOS(context)) { + if (AppTheme.isSpecializedMacOS(context)) { return 24; } else { - return SolianTheme.isLargeScreen(context) ? null : 24; + return AppTheme.isLargeScreen(context) ? null : 24; } } diff --git a/lib/widgets/app_bar_title.dart b/lib/widgets/app_bar_title.dart index 95bcb53..2e60680 100644 --- a/lib/widgets/app_bar_title.dart +++ b/lib/widgets/app_bar_title.dart @@ -8,7 +8,7 @@ class AppBarTitle extends StatelessWidget { @override Widget build(BuildContext context) { - if (SolianTheme.isSpecializedMacOS(context)) { + if (AppTheme.isSpecializedMacOS(context)) { return Text(title); } else { return Text(title); diff --git a/lib/widgets/channel/channel_call_indicator.dart b/lib/widgets/channel/channel_call_indicator.dart index 848cf42..5cca3f6 100644 --- a/lib/widgets/channel/channel_call_indicator.dart +++ b/lib/widgets/channel/channel_call_indicator.dart @@ -98,12 +98,12 @@ class ChannelCallIndicator extends StatelessWidget { child: Text('callJoin'.tr), ); } else if (call.channel.value?.id == channel.id && - !SolianTheme.isLargeScreen(context)) { + !AppTheme.isLargeScreen(context)) { return TextButton( onPressed: () => onJoin(), child: Text('callResume'.tr), ); - } else if (!SolianTheme.isLargeScreen(context)) { + } else if (!AppTheme.isLargeScreen(context)) { return TextButton( onPressed: null, child: Text('callJoin'.tr), diff --git a/lib/widgets/channel/channel_list.dart b/lib/widgets/channel/channel_list.dart index 865c995..785da91 100644 --- a/lib/widgets/channel/channel_list.dart +++ b/lib/widgets/channel/channel_list.dart @@ -11,6 +11,7 @@ class ChannelListWidget extends StatefulWidget { final List channels; final int selfId; final bool isDense; + final bool isCollapsed; final bool noCategory; final bool useReplace; final Function(Channel)? onSelected; @@ -20,6 +21,7 @@ class ChannelListWidget extends StatefulWidget { required this.channels, required this.selfId, this.isDense = false, + this.isCollapsed = false, this.noCategory = false, this.useReplace = false, this.onSelected, @@ -130,13 +132,25 @@ class _ChannelListWidgetState extends State { final otherside = item.members!.where((e) => e.account.id != widget.selfId).first; + final avatar = AccountAvatar( + content: otherside.account.avatar, + radius: widget.isDense ? 12 : 20, + bgColor: Theme.of(context).colorScheme.primary, + feColor: Theme.of(context).colorScheme.onPrimary, + ); + + if (widget.isCollapsed) { + return Tooltip( + message: otherside.account.nick, + child: InkWell( + child: avatar.paddingSymmetric(vertical: 12), + onTap: () => _gotoChannel(item), + ), + ); + } + return ListTile( - leading: AccountAvatar( - content: otherside.account.avatar, - radius: widget.isDense ? 12 : 20, - bgColor: Theme.of(context).colorScheme.primary, - feColor: Theme.of(context).colorScheme.onPrimary, - ), + leading: avatar, contentPadding: padding, title: Text(otherside.account.nick), subtitle: !widget.isDense @@ -145,21 +159,33 @@ class _ChannelListWidgetState extends State { onTap: () => _gotoChannel(item), ); } else { + final avatar = CircleAvatar( + backgroundColor: item.realmId == null + ? Theme.of(context).colorScheme.primary + : Colors.transparent, + radius: widget.isDense ? 12 : 20, + child: FaIcon( + FontAwesomeIcons.hashtag, + color: item.realmId == null + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.primary, + size: widget.isDense ? 12 : 16, + ), + ); + + if (widget.isCollapsed) { + return Tooltip( + message: item.name, + child: InkWell( + child: avatar.paddingSymmetric(vertical: 12), + onTap: () => _gotoChannel(item), + ), + ); + } + return ListTile( minTileHeight: widget.isDense ? 48 : null, - leading: CircleAvatar( - backgroundColor: item.realmId == null - ? Theme.of(context).colorScheme.primary - : Colors.transparent, - radius: widget.isDense ? 12 : 20, - child: FaIcon( - FontAwesomeIcons.hashtag, - color: item.realmId == null - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.primary, - size: widget.isDense ? 12 : 16, - ), - ), + leading: avatar, contentPadding: padding, title: Text(item.name), subtitle: !widget.isDense diff --git a/lib/widgets/chat/chat_event.dart b/lib/widgets/chat/chat_event.dart index 32047d0..ba7d575 100644 --- a/lib/widgets/chat/chat_event.dart +++ b/lib/widgets/chat/chat_event.dart @@ -75,9 +75,6 @@ class ChatEvent extends StatelessWidget { key: Key('m${item.uuid}attachments-box'), width: MediaQuery.of(context).size.width, padding: EdgeInsets.only(top: isMerged ? 0 : 4, bottom: 4), - constraints: const BoxConstraints( - maxHeight: 720, - ), child: AttachmentList( key: Key('m${item.uuid}attachments'), parentId: item.uuid, @@ -301,7 +298,10 @@ class ChatEvent extends StatelessWidget { ], ).paddingSymmetric(horizontal: 12), _buildLinkExpansion().paddingOnly(left: 52, right: 8), - _buildAttachment(context).paddingOnly(left: 56, right: 8), + _buildAttachment( + context, + isMinimal: ['messages.edit'].contains(item.type), + ).paddingOnly(left: 56, right: 8), ], ); } diff --git a/lib/widgets/chat/chat_message_input.dart b/lib/widgets/chat/chat_message_input.dart index 534f95c..0191f89 100644 --- a/lib/widgets/chat/chat_message_input.dart +++ b/lib/widgets/chat/chat_message_input.dart @@ -245,7 +245,8 @@ class _ChatMessageInputState extends State { _editTo = widget.edit!; _textController.text = body.text; _attachments.addAll( - widget.edit!.body['attachments']?.cast() ?? List.empty()); + widget.edit!.body['attachments']?.cast() ?? List.empty(), + ); } if (widget.reply != null) { _replyTo = widget.reply!; diff --git a/lib/widgets/navigation/app_navigation_drawer.dart b/lib/widgets/navigation/app_navigation_drawer.dart index 8d68a0c..58d3841 100644 --- a/lib/widgets/navigation/app_navigation_drawer.dart +++ b/lib/widgets/navigation/app_navigation_drawer.dart @@ -192,9 +192,9 @@ class _AppNavigationDrawerState extends State } void _autoResize() { - if (SolianTheme.isExtraLargeScreen(context)) { + if (AppTheme.isExtraLargeScreen(context)) { _expandDrawer(); - } else if (SolianTheme.isLargeScreen(context)) { + } else if (AppTheme.isLargeScreen(context)) { _collapseDrawer(); } else { _drawerAnimationController.value = 1; @@ -229,7 +229,7 @@ class _AppNavigationDrawerState extends State return Drawer( width: _drawerAnimation.value, backgroundColor: - SolianTheme.isLargeScreen(context) ? Colors.transparent : null, + AppTheme.isLargeScreen(context) ? Colors.transparent : null, child: child, ); }, @@ -247,20 +247,20 @@ class _AppNavigationDrawerState extends State alignment: WrapAlignment.spaceAround, children: AppNavigation.destinations .map( - (e) => Card( - elevation: 0, - margin: EdgeInsets.zero, - child: Tooltip( - message: e.label, - child: InkWell( - borderRadius: - const BorderRadius.all(Radius.circular(8)), - child: Icon(e.icon, size: 20).paddingAll(20), - onTap: () { - AppRouter.instance.goNamed(e.page); - _closeDrawer(); - }, - ), + (e) => Tooltip( + message: e.label, + child: InkWell( + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Icon( + e.icon, + size: 22, + color: Theme.of(context).colorScheme.onSurface, + ).paddingAll(16), + onTap: () { + AppRouter.instance.goNamed(e.page); + _closeDrawer(); + }, ), ), ) diff --git a/lib/widgets/navigation/app_navigation_region.dart b/lib/widgets/navigation/app_navigation_region.dart index d1488f1..c308395 100644 --- a/lib/widgets/navigation/app_navigation_region.dart +++ b/lib/widgets/navigation/app_navigation_region.dart @@ -20,62 +20,42 @@ class AppNavigationRegion extends StatefulWidget { State createState() => _AppNavigationRegionState(); } -class _AppNavigationRegionState extends State - with SingleTickerProviderStateMixin { +class _AppNavigationRegionState extends State { bool _isTryingExit = false; - late final AnimationController _animationController = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 250), - ); - late final Animation _animationTween = Tween( - begin: Offset.zero, - end: const Offset(1.0, 0.0), - ).animate(CurvedAnimation( - parent: _animationController, - curve: Curves.fastOutSlowIn, - )); - void _focusRealm(Realm item) { - _animationController.animateTo(1).then((_) { - setState( - () => Get.find().focusedRealm.value = item, - ); - _animationController.animateTo(0); - }); + setState( + () => Get.find().focusedRealm.value = item, + ); } void _unFocusRealm() { - _animationController.animateTo(1).then((_) { - setState( - () => Get.find().focusedRealm.value = null, - ); - _animationController.animateTo(0); - }); + setState( + () => Get.find().focusedRealm.value = null, + ); } @override void dispose() { - _animationController.dispose(); super.dispose(); } Widget _buildRealmFocusAvatar() { final focusedRealm = Get.find().focusedRealm.value; - return MouseRegion( - child: AnimatedSwitcher( - switchInCurve: Curves.fastOutSlowIn, - switchOutCurve: Curves.fastOutSlowIn, - duration: const Duration(milliseconds: 300), - transitionBuilder: (child, animation) { - return ScaleTransition( - scale: animation, - child: child, - ); - }, - child: _isTryingExit - ? GestureDetector( - child: CircleAvatar( + return GestureDetector( + child: MouseRegion( + child: AnimatedSwitcher( + switchInCurve: Curves.fastOutSlowIn, + switchOutCurve: Curves.fastOutSlowIn, + duration: const Duration(milliseconds: 300), + transitionBuilder: (child, animation) { + return ScaleTransition( + scale: animation, + child: child, + ); + }, + child: _isTryingExit + ? CircleAvatar( backgroundColor: Theme.of(context).colorScheme.primary, child: const Icon( Icons.arrow_back, @@ -84,13 +64,13 @@ class _AppNavigationRegionState extends State ), ).paddingSymmetric( vertical: 8, - ), - onTap: () => _unFocusRealm(), - ) - : _buildEntryAvatar(focusedRealm!), + ) + : _buildEntryAvatar(focusedRealm!), + ), + onEnter: (_) => setState(() => _isTryingExit = true), + onExit: (_) => setState(() => _isTryingExit = false), ), - onEnter: (_) => setState(() => _isTryingExit = true), - onExit: (_) => setState(() => _isTryingExit = false), + onTap: () => _unFocusRealm(), ); } @@ -113,11 +93,11 @@ class _AppNavigationRegionState extends State } Widget _buildEntry(BuildContext context, Realm item) { - const padding = EdgeInsets.symmetric(horizontal: 20); + const padding = EdgeInsets.symmetric(horizontal: 20, vertical: 8); if (widget.isCollapsed) { return InkWell( - child: _buildEntryAvatar(item), + child: _buildEntryAvatar(item).paddingSymmetric(vertical: 8), onTap: () => _focusRealm(item), ); } @@ -144,19 +124,27 @@ class _AppNavigationRegionState extends State final NavigationStateProvider navState = Get.find(); return Obx( - () => AnimatedBuilder( - animation: _animationController, - builder: (context, child) { + () => AnimatedSwitcher( + switchInCurve: Curves.fastOutSlowIn, + switchOutCurve: Curves.fastOutSlowIn, + duration: const Duration(milliseconds: 300), + transitionBuilder: (child, animation) { return SlideTransition( - position: _animationTween, - child: child, + position: Tween( + begin: const Offset(1.0, 0.0), + end: Offset.zero, + ).animate(animation), + child: Material( + color: Theme.of(context).colorScheme.surface, + child: child, + ), ); }, child: navState.focusedRealm.value == null ? widget.isCollapsed ? CustomScrollView( slivers: [ - const SliverPadding(padding: EdgeInsets.only(top: 8)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverList.builder( itemCount: realms.availableRealms.length, itemBuilder: (context, index) { @@ -171,7 +159,6 @@ class _AppNavigationRegionState extends State ) : CustomScrollView( slivers: [ - const SliverPadding(padding: EdgeInsets.only(top: 8)), SliverList.builder( itemCount: realms.availableRealms.length, itemBuilder: (context, index) { @@ -179,7 +166,6 @@ class _AppNavigationRegionState extends State return _buildEntry(context, element); }, ), - const SliverPadding(padding: EdgeInsets.only(bottom: 8)), ], ) : Column( @@ -187,8 +173,9 @@ class _AppNavigationRegionState extends State if (widget.isCollapsed) Tooltip( message: navState.focusedRealm.value!.name, - child: _buildRealmFocusAvatar().paddingSymmetric( - vertical: 8, + child: _buildRealmFocusAvatar().paddingOnly( + top: 24, + bottom: 8, ), ) else @@ -209,13 +196,12 @@ class _AppNavigationRegionState extends State Expanded( child: Obx( () => ChannelListWidget( + useReplace: true, channels: channels.availableChannels - .where( - (x) => - x.realm?.id == - navState.focusedRealm.value?.id, - ) + .where((x) => + x.realm?.id == navState.focusedRealm.value?.id) .toList(), + isCollapsed: widget.isCollapsed, selfId: auth.userProfile.value!['id'], noCategory: true, ), diff --git a/lib/widgets/posts/post_item.dart b/lib/widgets/posts/post_item.dart index 3e20a69..c8fc041 100644 --- a/lib/widgets/posts/post_item.dart +++ b/lib/widgets/posts/post_item.dart @@ -8,6 +8,7 @@ import 'package:intl/intl.dart'; import 'package:solian/models/post.dart'; import 'package:solian/screens/posts/post_detail.dart'; import 'package:solian/shells/title_shell.dart'; +import 'package:solian/theme.dart'; import 'package:solian/widgets/account/account_avatar.dart'; import 'package:solian/widgets/account/account_profile_popup.dart'; import 'package:solian/widgets/attachments/attachment_list.dart'; @@ -302,7 +303,7 @@ class _PostItemState extends State { autoload: false, isGrid: true, ).paddingOnly(left: 36, top: 4, bottom: 4); - } else if (attachments.length > 1) { + } else if (attachments.length > 1 || AppTheme.isLargeScreen(context)) { return AttachmentList( parentId: widget.item.id.toString(), attachmentsId: attachments, @@ -497,7 +498,10 @@ class _PostItemState extends State { ], ).paddingOnly( top: 10, - bottom: attachments.length == 1 ? 10 : 0, + bottom: + (attachments.length == 1 && !AppTheme.isLargeScreen(context)) + ? 10 + : 0, right: 16, left: 16, ), @@ -514,8 +518,13 @@ class _PostItemState extends State { }); }, ).paddingOnly( - top: attachments.length == 1 ? 10 : 6, - left: attachments.length == 1 ? 24 : 60, + top: (attachments.length == 1 && !AppTheme.isLargeScreen(context)) + ? 10 + : 6, + left: + (attachments.length == 1 && !AppTheme.isLargeScreen(context)) + ? 24 + : 60, right: 16, bottom: 10, )