♻️ Remove fab menu

This commit is contained in:
2025-12-27 22:01:54 +08:00
parent 804dd029b1
commit 836449e3f4
11 changed files with 191 additions and 506 deletions

View File

@@ -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",

View File

@@ -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);

View File

@@ -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<AppSettings> get copyWith => _$AppSettingsCopyWithImpl<AppS
@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)';
}
@@ -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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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 extends Object?>(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

View File

@@ -65,7 +65,7 @@ final class AppSettingsNotifierProvider
}
String _$appSettingsNotifierHash() =>
r'ef10d95a9f22e891ad6f5e0225e31508b3eb038e';
r'6592261baf8182fe78d3e58e2fd9bb53d3287736';
abstract class _$AppSettingsNotifier extends $Notifier<AppSettings> {
AppSettings build();

View File

@@ -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,

View File

@@ -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<List<String>>([]);
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,

View File

@@ -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(

View File

@@ -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<String>(
isExpanded: true,
items: [
DropdownMenuItem<String>(
value: 'left',
child: Text('Left').fontSize(14),
),
DropdownMenuItem<String>(
value: 'center',
child: Text('Center').fontSize(14),
),
DropdownMenuItem<String>(
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,

View File

@@ -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<CurrentRouteNotifier, String?>(
@@ -31,13 +28,13 @@ class CurrentRouteNotifier extends Notifier<String?> {
}
}
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<Widget>(
(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);
}
}

View File

@@ -125,7 +125,7 @@ final class RecentNotableDayProvider
}
}
String _$recentNotableDayHash() => r'780d0f0747d753c5d535d9c2413f8e68d457d974';
String _$recentNotableDayHash() => r'e0cc4a0e8016afe1c469a7c744dbab41e0d54c2d';
@ProviderFor(randomFortuneSaying)
const randomFortuneSayingProvider = RandomFortuneSayingProvider._();

View File

@@ -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, FabMenuType>(
FabMenuTypeNotifier.new,
);
class FabMenuTypeNotifier extends Notifier<FabMenuType> {
@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<void> _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 = <Widget>[
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 = <Widget>[
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,
);
},
);
}
}