From 836449e3f44c5dbf7be4f939b118c976d29d7453 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 27 Dec 2025 22:01:54 +0800 Subject: [PATCH] :recycle: Remove fab menu --- assets/i18n/en-US.json | 1 - lib/pods/config.dart | 9 - lib/pods/config.freezed.dart | 43 ++--- lib/pods/config.g.dart | 2 +- lib/screens/chat/chat.dart | 86 +++++++-- lib/screens/explore.dart | 65 +++++-- lib/screens/realm/realms.dart | 56 ++++-- lib/screens/settings.dart | 40 ---- lib/screens/tabs.dart | 119 ++---------- lib/widgets/check_in.g.dart | 2 +- lib/widgets/navigation/fab_menu.dart | 274 --------------------------- 11 files changed, 191 insertions(+), 506 deletions(-) delete mode 100644 lib/widgets/navigation/fab_menu.dart diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index b6e6fd8b..dc7e3529 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -1304,7 +1304,6 @@ "aiThought": "AI Thought", "aiThoughtTitle": "Let sn-chan think", "postReferenceUnavailable": "Referenced post is unavailable", - "fabLocation": "FAB Location", "activities": "Activities", "presenceTypeGaming": "Playing", "presenceTypeMusic": "Listening to Music", diff --git a/lib/pods/config.dart b/lib/pods/config.dart index 17b39c55..d55c3e20 100644 --- a/lib/pods/config.dart +++ b/lib/pods/config.dart @@ -33,7 +33,6 @@ const kAppDefaultPoolId = 'app_default_pool_id'; const kAppMessageDisplayStyle = 'app_message_display_style'; const kAppThemeMode = 'app_theme_mode'; const kAppDisableAnimation = 'app_disable_animation'; -const kAppFabPosition = 'app_fab_position'; const kAppGroupedChatList = 'app_grouped_chat_list'; const kFeaturedPostsCollapsedId = 'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post @@ -87,7 +86,6 @@ sealed class AppSettings with _$AppSettings { required String messageDisplayStyle, required String? themeMode, required bool disableAnimation, - required String fabPosition, required bool groupedChatList, required String? firstLaunchAt, required bool askedReview, @@ -119,7 +117,6 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { messageDisplayStyle: prefs.getString(kAppMessageDisplayStyle) ?? 'bubble', themeMode: prefs.getString(kAppThemeMode) ?? 'system', disableAnimation: prefs.getBool(kAppDisableAnimation) ?? false, - fabPosition: prefs.getString(kAppFabPosition) ?? 'center', groupedChatList: prefs.getBool(kAppGroupedChatList) ?? false, askedReview: prefs.getBool(kAppAskedReview) ?? false, firstLaunchAt: prefs.getString(kAppFirstLaunchAt), @@ -283,12 +280,6 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { state = state.copyWith(disableAnimation: value); } - void setFabPosition(String value) { - final prefs = ref.read(sharedPreferencesProvider); - prefs.setString(kAppFabPosition, value); - state = state.copyWith(fabPosition: value); - } - void setGroupedChatList(bool value) { final prefs = ref.read(sharedPreferencesProvider); prefs.setBool(kAppGroupedChatList, value); diff --git a/lib/pods/config.freezed.dart b/lib/pods/config.freezed.dart index ba31d9da..5257f381 100644 --- a/lib/pods/config.freezed.dart +++ b/lib/pods/config.freezed.dart @@ -290,7 +290,7 @@ mixin _$AppSettings { ThemeColors? get customColors; Size? get windowSize;// The window size for desktop platforms double get windowOpacity;// The window opacity for desktop platforms double get cardTransparency;// The card background opacity - String? get defaultPoolId; String get messageDisplayStyle; String? get themeMode; bool get disableAnimation; String get fabPosition; bool get groupedChatList; String? get firstLaunchAt; bool get askedReview; String? get dashSearchEngine; String? get defaultScreen; + String? get defaultPoolId; String get messageDisplayStyle; String? get themeMode; bool get disableAnimation; bool get groupedChatList; String? get firstLaunchAt; bool get askedReview; String? get dashSearchEngine; String? get defaultScreen; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -301,16 +301,16 @@ $AppSettingsCopyWith get copyWith => _$AppSettingsCopyWithImpl Object.hashAll([runtimeType,dataSavingMode,soundEffects,festivalFeatures,enterToSend,appBarTransparent,showBackgroundImage,notifyWithHaptic,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,disableAnimation,fabPosition,groupedChatList,firstLaunchAt,askedReview,dashSearchEngine,defaultScreen]); +int get hashCode => Object.hashAll([runtimeType,dataSavingMode,soundEffects,festivalFeatures,enterToSend,appBarTransparent,showBackgroundImage,notifyWithHaptic,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,disableAnimation,groupedChatList,firstLaunchAt,askedReview,dashSearchEngine,defaultScreen]); @override String toString() { - return 'AppSettings(dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, festivalFeatures: $festivalFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, notifyWithHaptic: $notifyWithHaptic, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, disableAnimation: $disableAnimation, fabPosition: $fabPosition, groupedChatList: $groupedChatList, firstLaunchAt: $firstLaunchAt, askedReview: $askedReview, dashSearchEngine: $dashSearchEngine, defaultScreen: $defaultScreen)'; + return 'AppSettings(dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, festivalFeatures: $festivalFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, notifyWithHaptic: $notifyWithHaptic, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, disableAnimation: $disableAnimation, groupedChatList: $groupedChatList, firstLaunchAt: $firstLaunchAt, askedReview: $askedReview, dashSearchEngine: $dashSearchEngine, defaultScreen: $defaultScreen)'; } @@ -321,7 +321,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> { factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl; @useResult $Res call({ - bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, String fabPosition, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen + bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen }); @@ -338,7 +338,7 @@ class _$AppSettingsCopyWithImpl<$Res> /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? dataSavingMode = null,Object? soundEffects = null,Object? festivalFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? notifyWithHaptic = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? disableAnimation = null,Object? fabPosition = null,Object? groupedChatList = null,Object? firstLaunchAt = freezed,Object? askedReview = null,Object? dashSearchEngine = freezed,Object? defaultScreen = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? dataSavingMode = null,Object? soundEffects = null,Object? festivalFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? notifyWithHaptic = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? disableAnimation = null,Object? groupedChatList = null,Object? firstLaunchAt = freezed,Object? askedReview = null,Object? dashSearchEngine = freezed,Object? defaultScreen = freezed,}) { return _then(_self.copyWith( dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable @@ -357,8 +357,7 @@ as double,defaultPoolId: freezed == defaultPoolId ? _self.defaultPoolId : defaul as String?,messageDisplayStyle: null == messageDisplayStyle ? _self.messageDisplayStyle : messageDisplayStyle // ignore: cast_nullable_to_non_nullable as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignore: cast_nullable_to_non_nullable as String?,disableAnimation: null == disableAnimation ? _self.disableAnimation : disableAnimation // ignore: cast_nullable_to_non_nullable -as bool,fabPosition: null == fabPosition ? _self.fabPosition : fabPosition // ignore: cast_nullable_to_non_nullable -as String,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable +as bool,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable as bool,firstLaunchAt: freezed == firstLaunchAt ? _self.firstLaunchAt : firstLaunchAt // ignore: cast_nullable_to_non_nullable as String?,askedReview: null == askedReview ? _self.askedReview : askedReview // ignore: cast_nullable_to_non_nullable as bool,dashSearchEngine: freezed == dashSearchEngine ? _self.dashSearchEngine : dashSearchEngine // ignore: cast_nullable_to_non_nullable @@ -457,10 +456,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, String fabPosition, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.fabPosition,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);case _: +return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);case _: return orElse(); } @@ -478,10 +477,10 @@ return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_ /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, String fabPosition, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen) $default,) {final _that = this; switch (_that) { case _AppSettings(): -return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.fabPosition,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);} +return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);} } /// A variant of `when` that fallback to returning `null` /// @@ -495,10 +494,10 @@ return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_ /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, String fabPosition, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen)? $default,) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.fabPosition,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);case _: +return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.notifyWithHaptic,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.disableAnimation,_that.groupedChatList,_that.firstLaunchAt,_that.askedReview,_that.dashSearchEngine,_that.defaultScreen);case _: return null; } @@ -510,7 +509,7 @@ return $default(_that.dataSavingMode,_that.soundEffects,_that.festivalFeatures,_ class _AppSettings implements AppSettings { - const _AppSettings({required this.dataSavingMode, required this.soundEffects, required this.festivalFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.notifyWithHaptic, required this.customFonts, required this.appColorScheme, required this.customColors, required this.windowSize, required this.windowOpacity, required this.cardTransparency, required this.defaultPoolId, required this.messageDisplayStyle, required this.themeMode, required this.disableAnimation, required this.fabPosition, required this.groupedChatList, required this.firstLaunchAt, required this.askedReview, required this.dashSearchEngine, required this.defaultScreen}); + const _AppSettings({required this.dataSavingMode, required this.soundEffects, required this.festivalFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.notifyWithHaptic, required this.customFonts, required this.appColorScheme, required this.customColors, required this.windowSize, required this.windowOpacity, required this.cardTransparency, required this.defaultPoolId, required this.messageDisplayStyle, required this.themeMode, required this.disableAnimation, required this.groupedChatList, required this.firstLaunchAt, required this.askedReview, required this.dashSearchEngine, required this.defaultScreen}); @override final bool dataSavingMode; @@ -534,7 +533,6 @@ class _AppSettings implements AppSettings { @override final String messageDisplayStyle; @override final String? themeMode; @override final bool disableAnimation; -@override final String fabPosition; @override final bool groupedChatList; @override final String? firstLaunchAt; @override final bool askedReview; @@ -551,16 +549,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.festivalFeatures, festivalFeatures) || other.festivalFeatures == festivalFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.notifyWithHaptic, notifyWithHaptic) || other.notifyWithHaptic == notifyWithHaptic)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.fabPosition, fabPosition) || other.fabPosition == fabPosition)&&(identical(other.groupedChatList, groupedChatList) || other.groupedChatList == groupedChatList)&&(identical(other.firstLaunchAt, firstLaunchAt) || other.firstLaunchAt == firstLaunchAt)&&(identical(other.askedReview, askedReview) || other.askedReview == askedReview)&&(identical(other.dashSearchEngine, dashSearchEngine) || other.dashSearchEngine == dashSearchEngine)&&(identical(other.defaultScreen, defaultScreen) || other.defaultScreen == defaultScreen)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.festivalFeatures, festivalFeatures) || other.festivalFeatures == festivalFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.notifyWithHaptic, notifyWithHaptic) || other.notifyWithHaptic == notifyWithHaptic)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.groupedChatList, groupedChatList) || other.groupedChatList == groupedChatList)&&(identical(other.firstLaunchAt, firstLaunchAt) || other.firstLaunchAt == firstLaunchAt)&&(identical(other.askedReview, askedReview) || other.askedReview == askedReview)&&(identical(other.dashSearchEngine, dashSearchEngine) || other.dashSearchEngine == dashSearchEngine)&&(identical(other.defaultScreen, defaultScreen) || other.defaultScreen == defaultScreen)); } @override -int get hashCode => Object.hashAll([runtimeType,dataSavingMode,soundEffects,festivalFeatures,enterToSend,appBarTransparent,showBackgroundImage,notifyWithHaptic,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,disableAnimation,fabPosition,groupedChatList,firstLaunchAt,askedReview,dashSearchEngine,defaultScreen]); +int get hashCode => Object.hashAll([runtimeType,dataSavingMode,soundEffects,festivalFeatures,enterToSend,appBarTransparent,showBackgroundImage,notifyWithHaptic,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,disableAnimation,groupedChatList,firstLaunchAt,askedReview,dashSearchEngine,defaultScreen]); @override String toString() { - return 'AppSettings(dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, festivalFeatures: $festivalFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, notifyWithHaptic: $notifyWithHaptic, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, disableAnimation: $disableAnimation, fabPosition: $fabPosition, groupedChatList: $groupedChatList, firstLaunchAt: $firstLaunchAt, askedReview: $askedReview, dashSearchEngine: $dashSearchEngine, defaultScreen: $defaultScreen)'; + return 'AppSettings(dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, festivalFeatures: $festivalFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, notifyWithHaptic: $notifyWithHaptic, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, disableAnimation: $disableAnimation, groupedChatList: $groupedChatList, firstLaunchAt: $firstLaunchAt, askedReview: $askedReview, dashSearchEngine: $dashSearchEngine, defaultScreen: $defaultScreen)'; } @@ -571,7 +569,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl; @override @useResult $Res call({ - bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, String fabPosition, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen + bool dataSavingMode, bool soundEffects, bool festivalFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, bool notifyWithHaptic, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool disableAnimation, bool groupedChatList, String? firstLaunchAt, bool askedReview, String? dashSearchEngine, String? defaultScreen }); @@ -588,7 +586,7 @@ class __$AppSettingsCopyWithImpl<$Res> /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? dataSavingMode = null,Object? soundEffects = null,Object? festivalFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? notifyWithHaptic = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? disableAnimation = null,Object? fabPosition = null,Object? groupedChatList = null,Object? firstLaunchAt = freezed,Object? askedReview = null,Object? dashSearchEngine = freezed,Object? defaultScreen = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? dataSavingMode = null,Object? soundEffects = null,Object? festivalFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? notifyWithHaptic = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? disableAnimation = null,Object? groupedChatList = null,Object? firstLaunchAt = freezed,Object? askedReview = null,Object? dashSearchEngine = freezed,Object? defaultScreen = freezed,}) { return _then(_AppSettings( dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable @@ -607,8 +605,7 @@ as double,defaultPoolId: freezed == defaultPoolId ? _self.defaultPoolId : defaul as String?,messageDisplayStyle: null == messageDisplayStyle ? _self.messageDisplayStyle : messageDisplayStyle // ignore: cast_nullable_to_non_nullable as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignore: cast_nullable_to_non_nullable as String?,disableAnimation: null == disableAnimation ? _self.disableAnimation : disableAnimation // ignore: cast_nullable_to_non_nullable -as bool,fabPosition: null == fabPosition ? _self.fabPosition : fabPosition // ignore: cast_nullable_to_non_nullable -as String,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable +as bool,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable as bool,firstLaunchAt: freezed == firstLaunchAt ? _self.firstLaunchAt : firstLaunchAt // ignore: cast_nullable_to_non_nullable as String?,askedReview: null == askedReview ? _self.askedReview : askedReview // ignore: cast_nullable_to_non_nullable as bool,dashSearchEngine: freezed == dashSearchEngine ? _self.dashSearchEngine : dashSearchEngine // ignore: cast_nullable_to_non_nullable diff --git a/lib/pods/config.g.dart b/lib/pods/config.g.dart index fcfea624..2e176bfd 100644 --- a/lib/pods/config.g.dart +++ b/lib/pods/config.g.dart @@ -65,7 +65,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'ef10d95a9f22e891ad6f5e0225e31508b3eb038e'; + r'6592261baf8182fe78d3e58e2fd9bb53d3287736'; abstract class _$AppSettingsNotifier extends $Notifier { AppSettings build(); diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index 14f3d306..2d7c7f17 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -9,15 +9,16 @@ import 'package:island/models/chat.dart'; import 'package:island/pods/chat/chat_summary.dart'; import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; +import 'package:island/screens/chat/chat_form.dart'; import 'package:island/screens/realm/realms.dart'; import 'package:island/services/event_bus.dart'; import 'package:island/services/responsive.dart'; +import 'package:island/widgets/account/account_picker.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/chat_room_widgets.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/sheet.dart'; -import 'package:island/widgets/navigation/fab_menu.dart'; import 'package:island/widgets/response.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -372,23 +373,6 @@ class ChatListScreen extends HookConsumerWidget { }; }, [tabController]); - useEffect(() { - // Set FAB type to chat - final fabMenuNotifier = ref.read(fabMenuTypeProvider.notifier); - Future(() { - fabMenuNotifier.setMenuType(FabMenuType.chat); - }); - return () { - // Clean up: reset FAB type to main - final fabMenu = ref.read(fabMenuTypeProvider); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (fabMenu == FabMenuType.chat) { - fabMenuNotifier.setMenuType(FabMenuType.main); - } - }); - }; - }, []); - if (isAside) { return Card( margin: EdgeInsets.zero, @@ -461,8 +445,74 @@ class ChatListScreen extends HookConsumerWidget { final appbarFeColor = Theme.of(context).appBarTheme.foregroundColor; + final userInfo = ref.watch(userInfoProvider); + return AppScaffold( extendBody: false, // Prevent conflicts with tabs navigation + floatingActionButton: userInfo.value != null + ? FloatingActionButton( + child: const Icon(Symbols.add), + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Gap(40), + ListTile( + title: const Text('createChatRoom').tr(), + leading: const Icon(Symbols.add), + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, + ), + onTap: () { + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) => const EditChatScreen(), + ).then((value) { + if (value != null) { + eventBus.fire(const ChatRoomsRefreshEvent()); + } + }); + }, + ), + ListTile( + title: const Text('createDirectMessage').tr(), + leading: const Icon(Symbols.person), + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, + ), + onTap: () async { + final result = await showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) => const AccountPickerSheet(), + ); + if (result == null) return; + final client = ref.read(apiClientProvider); + try { + await client.post( + '/sphere/chat/direct', + data: {'related_user_id': result.id}, + ); + eventBus.fire(const ChatRoomsRefreshEvent()); + } catch (err) { + showErrorAlert(err); + } + }, + ), + const Gap(16), + ], + ), + ); + }, + ).padding(bottom: isWideScreen(context) ? null : 56) + : null, appBar: AppBar( flexibleSpace: Container( height: 48, diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index c5d3e478..465e42c2 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -19,8 +19,8 @@ import 'package:island/services/responsive.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/models/post.dart'; import 'package:island/widgets/extended_refresh_indicator.dart'; -import 'package:island/widgets/navigation/fab_menu.dart'; import 'package:island/widgets/paging/pagination_list.dart'; +import 'package:island/widgets/post/compose_sheet.dart'; import 'package:island/widgets/post/post_item.dart'; import 'package:island/widgets/post/post_item_skeleton.dart'; import 'package:island/widgets/post/post_list.dart'; @@ -46,24 +46,6 @@ class ExploreScreen extends HookConsumerWidget { final selectedTagIds = useState>([]); final notifier = ref.watch(activityListProvider.notifier); - useEffect(() { - // Set FAB type to chat - - final fabMenuNotifier = ref.read(fabMenuTypeProvider.notifier); - Future(() { - fabMenuNotifier.setMenuType(FabMenuType.compose); - }); - return () { - // Clean up: reset FAB type to main - final fabMenu = ref.read(fabMenuTypeProvider); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (fabMenu == FabMenuType.compose) { - fabMenuNotifier.setMenuType(FabMenuType.main); - } - }); - }; - }, []); - void handleFilterChange(String? filter) { currentFilter.value = filter; notifier.applyFilter(filter); @@ -200,6 +182,8 @@ class ExploreScreen extends HookConsumerWidget { ).padding(horizontal: 8, vertical: 4), ); + final userInfo = ref.watch(userInfoProvider); + final appBar = isWide ? null : _buildAppBar( @@ -230,6 +214,49 @@ class ExploreScreen extends HookConsumerWidget { AppScaffold( isNoBackground: false, appBar: appBar, + floatingActionButton: userInfo.value != null + ? FloatingActionButton( + child: const Icon(Symbols.create), + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Gap(40), + ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, + ), + leading: const Icon(Symbols.post_add_rounded), + title: Text('postCompose').tr(), + onTap: () async { + Navigator.of(context).pop(); + await PostComposeSheet.show(context); + }, + ), + ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, + ), + leading: const Icon(Symbols.article), + title: Text('articleCompose').tr(), + onTap: () async { + Navigator.of(context).pop(); + GoRouter.of( + context, + ).pushNamed('articleCompose'); + }, + ), + const Gap(16), + ], + ), + ); + }, + ).padding(bottom: isWideScreen(context) ? null : 56) + : null, body: isWide ? _buildWideBody( context, diff --git a/lib/screens/realm/realms.dart b/lib/screens/realm/realms.dart index dedfbbb2..de947dc0 100644 --- a/lib/screens/realm/realms.dart +++ b/lib/screens/realm/realms.dart @@ -1,16 +1,16 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/realm.dart'; import 'package:island/pods/network.dart'; +import 'package:island/pods/userinfo.dart'; +import 'package:island/services/responsive.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/sheet.dart'; -import 'package:island/widgets/navigation/fab_menu.dart'; import 'package:island/widgets/response.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -43,22 +43,7 @@ class RealmListScreen extends HookConsumerWidget { final realms = ref.watch(realmsJoinedProvider); final realmInvites = ref.watch(realmInvitesProvider); - useEffect(() { - // Set FAB type to realm - final fabMenuNotifier = ref.read(fabMenuTypeProvider.notifier); - Future(() { - fabMenuNotifier.setMenuType(FabMenuType.realm); - }); - return () { - // Clean up: reset FAB type to main - final fabMenu = ref.read(fabMenuTypeProvider); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (fabMenu == FabMenuType.realm) { - fabMenuNotifier.setMenuType(FabMenuType.main); - } - }); - }; - }, []); + final userInfo = ref.watch(userInfoProvider); return AppScaffold( isNoBackground: false, @@ -98,6 +83,41 @@ class RealmListScreen extends HookConsumerWidget { const Gap(8), ], ), + floatingActionButton: userInfo.value != null + ? FloatingActionButton( + child: const Icon(Symbols.add), + onPressed: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Gap(40), + ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, + ), + leading: const Icon(Symbols.group_add), + title: Text('createRealm').tr(), + onTap: () { + Navigator.of(context).pop(); + context.pushNamed('realmNew').then((value) { + if (value != null) { + // Fire realm refresh event if needed + // eventBus.fire(const RealmsRefreshEvent()); + } + }); + }, + ), + const Gap(16), + ], + ), + ); + }, + ).padding(bottom: isWideScreen(context) ? null : 56) + : null, body: ExtendedRefreshIndicator( child: realms.when( data: (value) => Column( diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index 2399cb19..efa7d282 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -407,46 +407,6 @@ class SettingsScreen extends HookConsumerWidget { ), ), - // FAB position settings - ListTile( - minLeadingWidth: 48, - title: Text('fabLocation').tr(), - contentPadding: const EdgeInsets.only(left: 24, right: 17), - leading: const Icon(Symbols.adjust), - trailing: DropdownButtonHideUnderline( - child: DropdownButton2( - isExpanded: true, - items: [ - DropdownMenuItem( - value: 'left', - child: Text('Left').fontSize(14), - ), - DropdownMenuItem( - value: 'center', - child: Text('Center').fontSize(14), - ), - DropdownMenuItem( - value: 'right', - child: Text('Right').fontSize(14), - ), - ], - value: settings.fabPosition, - onChanged: (String? value) { - if (value != null) { - ref.read(appSettingsProvider.notifier).setFabPosition(value); - showSnackBar('settingsApplied'.tr()); - } - }, - buttonStyleData: const ButtonStyleData( - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 5), - height: 40, - width: 120, - ), - menuItemStyleData: const MenuItemStyleData(height: 40), - ), - ), - ), - // Card background opacity settings ListTile( isThreeLine: true, diff --git a/lib/screens/tabs.dart b/lib/screens/tabs.dart index 140b5ae3..05222031 100644 --- a/lib/screens/tabs.dart +++ b/lib/screens/tabs.dart @@ -10,10 +10,7 @@ import 'package:island/screens/notification.dart'; import 'package:island/services/responsive.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/navigation/conditional_bottom_nav.dart'; -import 'package:island/widgets/navigation/fab_menu.dart'; import 'package:material_symbols_icons/symbols.dart'; -import 'package:styled_widget/styled_widget.dart'; -import 'package:island/pods/config.dart'; import 'package:island/pods/chat/chat_summary.dart'; final currentRouteProvider = NotifierProvider( @@ -31,13 +28,13 @@ class CurrentRouteNotifier extends Notifier { } } -const kWideScreenRouteStart = 4; +const kWideScreenRouteStart = 5; const kTabRoutes = [ '/', '/explore', '/chat', - '/account', '/realms', + '/account', '/files', '/thought', '/creators', @@ -84,7 +81,10 @@ class TabsScreen extends HookConsumerWidget { child: const Icon(Symbols.forum_rounded), ), ), - + NavigationDestination( + label: 'realms'.tr(), + icon: const Icon(Symbols.group_rounded), + ), NavigationDestination( label: 'account'.tr(), icon: Badge.count( @@ -107,10 +107,6 @@ class TabsScreen extends HookConsumerWidget { ), if (wideScreen) ...([ - NavigationDestination( - label: 'realms'.tr(), - icon: const Icon(Symbols.group_rounded), - ), NavigationDestination( label: 'files'.tr(), icon: const Icon(Symbols.folder_rounded), @@ -146,13 +142,6 @@ class TabsScreen extends HookConsumerWidget { final currentIndex = getCurrentIndex(); - final routes = kTabRoutes.sublist( - 0, - isWideScreen(context) ? null : kWideScreenRouteStart, - ); - final shouldShowFab = routes.contains(currentLocation) && !wideScreen; - final settings = ref.watch(appSettingsProvider); - if (isWideScreen(context)) { return Container( color: Theme.of(context).colorScheme.surfaceContainer, @@ -170,10 +159,6 @@ class TabsScreen extends HookConsumerWidget { .toList(), selectedIndex: currentIndex, onDestinationSelected: onDestinationSelected, - trailingAtBottom: true, - trailing: const FabMenu( - elevation: 0, - ).padding(bottom: MediaQuery.of(context).padding.bottom + 16), ), Expanded( child: ClipRRect( @@ -199,10 +184,6 @@ class TabsScreen extends HookConsumerWidget { ), child: child ?? const SizedBox.shrink(), ), - floatingActionButton: shouldShowFab ? const FabMenu() : null, - floatingActionButtonLocation: shouldShowFab - ? _DockedFabLocation(context, settings.fabPosition) - : null, bottomNavigationBar: ConditionalBottomNav( child: ClipRRect( borderRadius: BorderRadius.only( @@ -225,47 +206,18 @@ class TabsScreen extends HookConsumerWidget { ), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), - child: BottomAppBar( + child: NavigationBar( height: 56, - padding: EdgeInsets.symmetric(horizontal: 24), - shape: AutomaticNotchedShape( - RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(16)), - ), - ), - color: Theme.of(context).colorScheme.surface.withOpacity(0.8), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: () { - final navItems = destinations.asMap().entries.map( - (entry) { - int index = entry.key; - NavigationDestination dest = entry.value; - return IconButton( - icon: dest.icon, - onPressed: () => onDestinationSelected(index), - color: index == currentIndex - ? Theme.of(context).colorScheme.primary - : null, - ); - }, - ).toList(); - // Add mock item to leave space for FAB based on position - final gapIndex = switch (settings.fabPosition) { - 'left' => 0, - 'right' => navItems.length, - _ => navItems.length ~/ 2, // center - }; - navItems.insert( - gapIndex, - SizedBox( - width: settings.fabPosition == 'center' ? 72 : 48, - ), - ); - return navItems; - }(), - ), + destinations: destinations, + selectedIndex: currentIndex, + onDestinationSelected: onDestinationSelected, + labelBehavior: NavigationDestinationLabelBehavior.alwaysHide, + backgroundColor: Theme.of( + context, + ).colorScheme.surface.withOpacity(0.8), + indicatorColor: Theme.of( + context, + ).colorScheme.primary.withOpacity(0.2), ), ), ), @@ -275,40 +227,3 @@ class TabsScreen extends HookConsumerWidget { ); } } - -class _DockedFabLocation extends FloatingActionButtonLocation { - final BuildContext context; - final String fabPosition; - - const _DockedFabLocation(this.context, this.fabPosition); - - @override - Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) { - final mediaQuery = MediaQuery.of(context); - final safeAreaPadding = mediaQuery.padding; - - // Position horizontally based on setting - final double fabX = switch (fabPosition) { - 'left' => scaffoldGeometry.minInsets.left + 24, - 'right' => - scaffoldGeometry.scaffoldSize.width - - scaffoldGeometry.floatingActionButtonSize.width - - scaffoldGeometry.minInsets.right - - 24, - _ => - (scaffoldGeometry.scaffoldSize.width - - scaffoldGeometry.floatingActionButtonSize.width) / - 2, // center - }; - - // Position closer to bottom with reduced padding - final double fabY = - scaffoldGeometry.scaffoldSize.height - - scaffoldGeometry.floatingActionButtonSize.height - - scaffoldGeometry.bottomSheetSize.height - - safeAreaPadding.bottom - - 16; - - return Offset(fabX, fabY); - } -} diff --git a/lib/widgets/check_in.g.dart b/lib/widgets/check_in.g.dart index b66eeceb..2ade1fbf 100644 --- a/lib/widgets/check_in.g.dart +++ b/lib/widgets/check_in.g.dart @@ -125,7 +125,7 @@ final class RecentNotableDayProvider } } -String _$recentNotableDayHash() => r'780d0f0747d753c5d535d9c2413f8e68d457d974'; +String _$recentNotableDayHash() => r'e0cc4a0e8016afe1c469a7c744dbab41e0d54c2d'; @ProviderFor(randomFortuneSaying) const randomFortuneSayingProvider = RandomFortuneSayingProvider._(); diff --git a/lib/widgets/navigation/fab_menu.dart b/lib/widgets/navigation/fab_menu.dart deleted file mode 100644 index fd46dee1..00000000 --- a/lib/widgets/navigation/fab_menu.dart +++ /dev/null @@ -1,274 +0,0 @@ -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:gap/gap.dart'; -import 'package:go_router/go_router.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:island/pods/network.dart'; -import 'package:island/pods/userinfo.dart'; -import 'package:island/screens/auth/create_account_modal.dart'; -import 'package:island/screens/auth/login_modal.dart'; -import 'package:island/screens/notification.dart'; -import 'package:island/services/event_bus.dart'; -import 'package:island/services/responsive.dart'; -import 'package:island/widgets/account/account_picker.dart'; -import 'package:island/widgets/alert.dart'; -import 'package:island/widgets/post/compose_sheet.dart'; -import 'package:island/screens/chat/chat_form.dart'; -import 'package:material_symbols_icons/symbols.dart'; - -enum FabMenuType { main, compose, chat, realm } - -/// Global state provider for FAB menu type -final fabMenuTypeProvider = NotifierProvider( - FabMenuTypeNotifier.new, -); - -class FabMenuTypeNotifier extends Notifier { - @override - FabMenuType build() { - return FabMenuType.main; - } - - void setMenuType(FabMenuType menuType) { - state = menuType; - } -} - -class FabMenu extends HookConsumerWidget { - final double? elevation; - const FabMenu({super.key, this.elevation}); - - Future _createDirectMessage(BuildContext context, WidgetRef ref) async { - final result = await showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) => const AccountPickerSheet(), - ); - if (result == null) return; - final client = ref.read(apiClientProvider); - try { - await client.post( - '/sphere/chat/direct', - data: {'related_user_id': result.id}, - ); - eventBus.fire(const ChatRoomsRefreshEvent()); - } catch (err) { - showErrorAlert(err); - } - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - final fabType = ref.watch(fabMenuTypeProvider); - - late final IconData icon; - late final bool useRootNavigator; - late final Widget menuContent; - - final unauthorizedEntires = [ - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.login), - title: Text('login').tr(), - onTap: () async { - showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) => LoginModal(), - ); - }, - ), - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.person_add), - title: Text('createAccount').tr(), - onTap: () async { - showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) => CreateAccountModal(), - ); - }, - ), - ]; - - final authorizedEntires = [ - if (!isWideScreen(context)) - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.bubble_chart), - title: Text('aiThoughtTitle').tr(), - onTap: () async { - Navigator.of(context).pop(); - context.goNamed('thought'); - }, - ), - Consumer( - builder: (context, ref, _) { - final notificationCount = ref.watch(notificationUnreadCountProvider); - return ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.notifications), - trailing: Badge( - label: Text(notificationCount.value.toString()), - isLabelVisible: notificationCount.value! > 0, - ), - title: Text('notifications').tr(), - onTap: () async { - Navigator.of(context).pop(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - useRootNavigator: true, - builder: (context) => const NotificationSheet(), - ); - }, - ); - }, - ), - ]; - - final userInfo = ref.watch(userInfoProvider); - final authorized = userInfo.value != null; - final commonEntires = authorized ? authorizedEntires : unauthorizedEntires; - - switch (fabType) { - case FabMenuType.compose: - icon = Symbols.create; - useRootNavigator = false; - menuContent = Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Gap(24), - if (authorized) - ...([ - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.post_add_rounded), - title: Text('postCompose').tr(), - onTap: () async { - Navigator.of(context).pop(); - await PostComposeSheet.show(context); - }, - ), - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.article), - title: Text('articleCompose').tr(), - onTap: () async { - Navigator.of(context).pop(); - GoRouter.of(context).pushNamed('articleCompose'); - }, - ), - const Divider(), - ]), - ...commonEntires, - Gap(MediaQuery.of(context).padding.bottom + 16), - ], - ); - break; - - case FabMenuType.chat: - icon = Symbols.chat_add_on; - useRootNavigator = true; - menuContent = Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Gap(24), - if (authorized) - ...([ - ListTile( - title: const Text('createChatRoom').tr(), - leading: const Icon(Symbols.add), - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - onTap: () { - showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) => const EditChatScreen(), - ).then((value) { - if (value != null) { - eventBus.fire(const ChatRoomsRefreshEvent()); - } - }); - }, - ), - ListTile( - title: const Text('createDirectMessage').tr(), - leading: const Icon(Symbols.person), - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - onTap: () { - _createDirectMessage(context, ref); - }, - ), - const Divider(), - ]), - ...commonEntires, - Gap(MediaQuery.of(context).padding.bottom + 16), - ], - ); - break; - - case FabMenuType.realm: - icon = Symbols.group_add; - useRootNavigator = false; - menuContent = Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Gap(24), - if (authorized) - ...([ - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 24), - leading: const Icon(Symbols.group_add), - title: Text('createRealm').tr(), - onTap: () { - Navigator.of(context).pop(); - context.pushNamed('realmNew').then((value) { - if (value != null) { - // Fire realm refresh event if needed - // eventBus.fire(const RealmsRefreshEvent()); - } - }); - }, - ), - const Divider(), - ]), - ...commonEntires, - Gap(MediaQuery.of(context).padding.bottom + 16), - ], - ); - break; - - case FabMenuType.main: - icon = Symbols.menu; - useRootNavigator = false; - menuContent = Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Gap(24), - ...commonEntires, - Gap(MediaQuery.of(context).padding.bottom + 16), - ], - ); - break; - } - - return FloatingActionButton( - elevation: elevation, - child: Icon(icon), - onPressed: () { - showModalBottomSheet( - context: context, - useRootNavigator: useRootNavigator, - builder: (BuildContext context) => menuContent, - ); - }, - ); - } -}