diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 56ee690c..4c714e37 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -1533,5 +1533,6 @@ "pinChatRoomDescription": "Pin this chat room to the top.", "chatRoomPinned": "Chat room pinned successfully.", "chatRoomUnpinned": "Chat room unpinned successfully.", - "pinnedChatRoom": "Pinned Rooms" + "pinnedChatRoom": "Pinned Rooms", + "settingsGroupedChatList": "Grouped Chat List" } diff --git a/lib/pods/chat/chat_room.g.dart b/lib/pods/chat/chat_room.g.dart index 0c185829..25db94bc 100644 --- a/lib/pods/chat/chat_room.g.dart +++ b/lib/pods/chat/chat_room.g.dart @@ -34,7 +34,7 @@ final class ChatRoomJoinedNotifierProvider } String _$chatRoomJoinedNotifierHash() => - r'805b38e477df574c92b1ef3cd54527cfd03a55cb'; + r'e69955be56ef2c04a8062a8a65925e0a23bfcbaa'; abstract class _$ChatRoomJoinedNotifier extends $AsyncNotifier> { diff --git a/lib/pods/config.dart b/lib/pods/config.dart index 1348d0dc..8efca68f 100644 --- a/lib/pods/config.dart +++ b/lib/pods/config.dart @@ -36,6 +36,7 @@ const kAppThemeMode = 'app_theme_mode'; const kMaterialYouToggleStoreKey = 'app_theme_material_you'; 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 @@ -100,6 +101,7 @@ sealed class AppSettings with _$AppSettings { required bool useMaterial3, required bool disableAnimation, required String fabPosition, + required bool groupedChatList, }) = _AppSettings; } @@ -128,6 +130,7 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { useMaterial3: prefs.getBool(kMaterialYouToggleStoreKey) ?? true, disableAnimation: prefs.getBool(kAppDisableAnimation) ?? false, fabPosition: prefs.getString(kAppFabPosition) ?? 'center', + groupedChatList: prefs.getBool(kAppGroupedChatList) ?? false, ); } @@ -291,6 +294,12 @@ class AppSettingsNotifier extends _$AppSettingsNotifier { prefs.setString(kAppFabPosition, value); state = state.copyWith(fabPosition: value); } + + void setGroupedChatList(bool value) { + final prefs = ref.read(sharedPreferencesProvider); + prefs.setBool(kAppGroupedChatList, value); + state = state.copyWith(groupedChatList: value); + } } final updateInfoProvider = diff --git a/lib/pods/config.freezed.dart b/lib/pods/config.freezed.dart index 89b1871e..03289830 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 useMaterial3; bool get disableAnimation; String get fabPosition; + String? get defaultPoolId; String get messageDisplayStyle; String? get themeMode; bool get useMaterial3; bool get disableAnimation; String get fabPosition; bool get groupedChatList; /// 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,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition]); +int get hashCode => Object.hashAll([runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition,groupedChatList]); @override String toString() { - return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition)'; + return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition, groupedChatList: $groupedChatList)'; } @@ -321,7 +321,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> { factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl; @useResult $Res call({ - bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition + bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition, bool groupedChatList }); @@ -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? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = 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? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = 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? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,Object? groupedChatList = null,}) { return _then(_self.copyWith( autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable @@ -359,7 +359,8 @@ as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignor as String?,useMaterial3: null == useMaterial3 ? _self.useMaterial3 : useMaterial3 // ignore: cast_nullable_to_non_nullable as bool,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, +as String,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable +as bool, )); } /// Create a copy of AppSettings @@ -453,10 +454,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition, bool groupedChatList)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);case _: +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition,_that.groupedChatList);case _: return orElse(); } @@ -474,10 +475,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition, bool groupedChatList) $default,) {final _that = this; switch (_that) { case _AppSettings(): -return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);} +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition,_that.groupedChatList);} } /// A variant of `when` that fallback to returning `null` /// @@ -491,10 +492,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition, bool groupedChatList)? $default,) {final _that = this; switch (_that) { case _AppSettings() when $default != null: -return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);case _: +return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition,_that.groupedChatList);case _: return null; } @@ -506,7 +507,7 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha class _AppSettings implements AppSettings { - const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, 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.useMaterial3, required this.disableAnimation, required this.fabPosition}); + const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, 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.useMaterial3, required this.disableAnimation, required this.fabPosition, required this.groupedChatList}); @override final bool autoTranslate; @@ -532,6 +533,7 @@ class _AppSettings implements AppSettings { @override final bool useMaterial3; @override final bool disableAnimation; @override final String fabPosition; +@override final bool groupedChatList; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -543,16 +545,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(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.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.fabPosition, fabPosition) || other.fabPosition == fabPosition)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(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.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.fabPosition, fabPosition) || other.fabPosition == fabPosition)&&(identical(other.groupedChatList, groupedChatList) || other.groupedChatList == groupedChatList)); } @override -int get hashCode => Object.hashAll([runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition]); +int get hashCode => Object.hashAll([runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition,groupedChatList]); @override String toString() { - return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition)'; + return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition, groupedChatList: $groupedChatList)'; } @@ -563,7 +565,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl; @override @useResult $Res call({ - bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition + bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition, bool groupedChatList }); @@ -580,7 +582,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? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = 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? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = 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? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,Object? groupedChatList = null,}) { return _then(_AppSettings( autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable @@ -601,7 +603,8 @@ as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignor as String?,useMaterial3: null == useMaterial3 ? _self.useMaterial3 : useMaterial3 // ignore: cast_nullable_to_non_nullable as bool,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, +as String,groupedChatList: null == groupedChatList ? _self.groupedChatList : groupedChatList // ignore: cast_nullable_to_non_nullable +as bool, )); } diff --git a/lib/pods/config.g.dart b/lib/pods/config.g.dart index 3fb10d15..8e4a153f 100644 --- a/lib/pods/config.g.dart +++ b/lib/pods/config.g.dart @@ -65,7 +65,7 @@ final class AppSettingsNotifierProvider } String _$appSettingsNotifierHash() => - r'22b695f2023e3251db3296858acd701f7211d757'; + r'46ac63d6febb9a13f414faa17feb1ac4c1e22c60'; abstract class _$AppSettingsNotifier extends $Notifier { AppSettings build(); diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index a77ddf37..07e1de12 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -15,12 +15,14 @@ import 'package:island/services/responsive.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'; import 'package:island/pods/chat/chat_room.dart'; +import 'package:island/pods/config.dart'; import 'package:super_sliver_list/super_sliver_list.dart'; class ChatListBodyWidget extends HookConsumerWidget { @@ -38,6 +40,7 @@ class ChatListBodyWidget extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final chats = ref.watch(chatRoomJoinedProvider); + final settings = ref.watch(appSettingsProvider); Widget bodyWidget = Column( children: [ @@ -75,6 +78,7 @@ class ChatListBodyWidget extends HookConsumerWidget { }), child: Column( children: [ + // Always show pinned chats in their own section ExpansionTile( backgroundColor: Theme.of( context, @@ -108,35 +112,169 @@ class ChatListBodyWidget extends HookConsumerWidget { ], ), Expanded( - child: SuperListView.builder( - padding: EdgeInsets.only(bottom: 96), - itemCount: unpinnedItems - .where( - (item) => - selectedTab.value == 0 || - (selectedTab.value == 1 && item.type == 1) || - (selectedTab.value == 2 && item.type != 1), - ) - .length, - itemBuilder: (context, index) { - final item = unpinnedItems[index]; - return ChatRoomListTile( - room: item, - isDirect: item.type == 1, - onTap: () { - if (isWideScreen(context)) { - context.replaceNamed( - 'chatRoom', - pathParameters: {'id': item.id}, - ); - } else { - context.pushNamed( - 'chatRoom', - pathParameters: {'id': item.id}, - ); + child: Consumer( + builder: (context, ref, _) { + final summaries = + ref + .watch(chatSummaryProvider) + .whenData((data) => data) + .value ?? + {}; + + if (settings.groupedChatList && + selectedTab.value == 0) { + // Group by realm (include both pinned and unpinned) + final realmGroups = >{}; + final ungrouped = []; + + for (final item in filteredItems) { + if (item.realmId != null) { + realmGroups + .putIfAbsent(item.realmId, () => []) + .add(item); + } else if (!item.isPinned) { + // Only unpinned chats without realm go to ungrouped + ungrouped.add(item); } - }, - ); + } + + final children = []; + + // Add realm groups + for (final entry in realmGroups.entries) { + final rooms = entry.value; + final realm = rooms.first.realm; + final realmName = realm?.name ?? 'Unknown Realm'; + + // Calculate total unread count for this realm + final totalUnread = rooms.fold( + 0, + (sum, room) => + sum + + (summaries[room.id]?.unreadCount ?? 0), + ); + + children.add( + ExpansionTile( + backgroundColor: Theme.of(context) + .colorScheme + .surfaceContainer + .withOpacity(0.5), + collapsedBackgroundColor: Theme.of(context) + .colorScheme + .surfaceContainer + .withOpacity(0.5), + title: Row( + children: [ + Expanded(child: Text(realmName)), + Badge( + isLabelVisible: totalUnread > 0, + label: Text(totalUnread.toString()), + backgroundColor: Theme.of( + context, + ).colorScheme.primary, + textColor: Theme.of( + context, + ).colorScheme.onPrimary, + ), + ], + ), + leading: ProfilePictureWidget( + file: realm?.picture, + radius: 16, + ), + tilePadding: const EdgeInsets.only( + left: 20, + right: 24, + ), + children: rooms.map((room) { + return ChatRoomListTile( + room: room, + isDirect: room.type == 1, + onTap: () { + if (isWideScreen(context)) { + context.replaceNamed( + 'chatRoom', + pathParameters: {'id': room.id}, + ); + } else { + context.pushNamed( + 'chatRoom', + pathParameters: {'id': room.id}, + ); + } + }, + ); + }).toList(), + ), + ); + } + + // Add ungrouped chats + if (ungrouped.isNotEmpty) { + children.addAll( + ungrouped.map((room) { + return ChatRoomListTile( + room: room, + isDirect: room.type == 1, + onTap: () { + if (isWideScreen(context)) { + context.replaceNamed( + 'chatRoom', + pathParameters: {'id': room.id}, + ); + } else { + context.pushNamed( + 'chatRoom', + pathParameters: {'id': room.id}, + ); + } + }, + ); + }), + ); + } + + return ListView( + padding: EdgeInsets.only(bottom: 96), + children: children, + ); + } else { + // Normal list view + return SuperListView.builder( + padding: EdgeInsets.only(bottom: 96), + itemCount: unpinnedItems + .where( + (item) => + selectedTab.value == 0 || + (selectedTab.value == 1 && + item.type == 1) || + (selectedTab.value == 2 && + item.type != 1), + ) + .length, + itemBuilder: (context, index) { + final item = unpinnedItems[index]; + return ChatRoomListTile( + room: item, + isDirect: item.type == 1, + onTap: () { + if (isWideScreen(context)) { + context.replaceNamed( + 'chatRoom', + pathParameters: {'id': item.id}, + ); + } else { + context.pushNamed( + 'chatRoom', + pathParameters: {'id': item.id}, + ); + } + }, + ); + }, + ); + } }, ), ), diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index f28d92c4..11a41898 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -819,6 +819,20 @@ class SettingsScreen extends HookConsumerWidget { }, ), ), + + // Grouped chat list settings + ListTile( + minLeadingWidth: 48, + title: Text('settingsGroupedChatList').tr(), + contentPadding: const EdgeInsets.only(left: 24, right: 17), + leading: const Icon(Symbols.chat), + trailing: Switch( + value: settings.groupedChatList, + onChanged: (value) { + ref.read(appSettingsProvider.notifier).setGroupedChatList(value); + }, + ), + ), ]; // Desktop-specific settings