diff --git a/lib/pods/config.dart b/lib/pods/config.dart index 2a38b31..59491e9 100644 --- a/lib/pods/config.dart +++ b/lib/pods/config.dart @@ -23,6 +23,8 @@ const kAppSoundEffects = 'app_sound_effects'; const kAppAprilFoolFeatures = 'app_april_fool_features'; const kAppWindowSize = 'app_window_size'; const kAppEnterToSend = 'app_enter_to_send'; +const kFeaturedPostsCollapsedId = + 'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post const Map kImageQualityLevel = { 'settingsImageQualityLowest': FilterQuality.none, diff --git a/lib/widgets/post/post_featured.dart b/lib/widgets/post/post_featured.dart index fba18e4..66625c0 100644 --- a/lib/widgets/post/post_featured.dart +++ b/lib/widgets/post/post_featured.dart @@ -7,6 +7,7 @@ import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:island/widgets/post/post_item.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:island/pods/config.dart'; // Import config.dart for shared preferences keys and provider part 'post_featured.g.dart'; @@ -25,7 +26,13 @@ class PostFeaturedList extends HookConsumerWidget { final featuredPostsAsync = ref.watch(featuredPostsProvider); final pageViewController = usePageController(); + final prefs = ref.watch(sharedPreferencesProvider); final pageViewCurrent = useState(0); + final previousFirstPostId = useState(null); + final storedCollapsedId = useState( + prefs.getString(kFeaturedPostsCollapsedId), + ); + final isCollapsed = useState(false); useEffect(() { pageViewController.addListener(() { @@ -34,6 +41,59 @@ class PostFeaturedList extends HookConsumerWidget { return null; }, [pageViewController]); + // Log isCollapsed state changes + useEffect(() { + debugPrint( + 'PostFeaturedList: isCollapsed changed to ${isCollapsed.value}', + ); + return null; + }, [isCollapsed.value]); + + useEffect(() { + if (featuredPostsAsync.hasValue && featuredPostsAsync.value!.isNotEmpty) { + final currentFirstPostId = featuredPostsAsync.value!.first.id; + debugPrint( + 'PostFeaturedList: Current first post ID: $currentFirstPostId', + ); + debugPrint( + 'PostFeaturedList: Previous first post ID: ${previousFirstPostId.value}', + ); + debugPrint( + 'PostFeaturedList: Stored collapsed ID: ${storedCollapsedId.value}', + ); + + if (previousFirstPostId.value == null) { + // Initial load + previousFirstPostId.value = currentFirstPostId; + isCollapsed.value = (storedCollapsedId.value == currentFirstPostId); + debugPrint( + 'PostFeaturedList: Initial load. isCollapsed set to ${isCollapsed.value}', + ); + } else if (previousFirstPostId.value != currentFirstPostId) { + // First post changed, expand by default + previousFirstPostId.value = currentFirstPostId; + isCollapsed.value = false; + prefs.remove( + kFeaturedPostsCollapsedId, + ); // Clear stored ID if post changes + debugPrint( + 'PostFeaturedList: First post changed. isCollapsed set to false.', + ); + } else { + // Same first post, maintain current collapse state + // No change needed for isCollapsed.value unless manually toggled + debugPrint( + 'PostFeaturedList: Same first post. Maintaining current collapse state.', + ); + } + } else { + debugPrint( + 'PostFeaturedList: featuredPostsAsync has no value or is empty.', + ); + } + return null; + }, [featuredPostsAsync.value]); + return ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(8)), child: Card( @@ -73,29 +133,69 @@ class PostFeaturedList extends HookConsumerWidget { }, icon: const Icon(Symbols.arrow_right), ), + IconButton( + padding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + constraints: const BoxConstraints(), + onPressed: () { + isCollapsed.value = !isCollapsed.value; + debugPrint( + 'PostFeaturedList: Manual toggle. isCollapsed set to ${isCollapsed.value}', + ); + if (isCollapsed.value && + featuredPostsAsync.hasValue && + featuredPostsAsync.value!.isNotEmpty) { + prefs.setString( + kFeaturedPostsCollapsedId, + featuredPostsAsync.value!.first.id, + ); + debugPrint( + 'PostFeaturedList: Stored collapsed ID: ${featuredPostsAsync.value!.first.id}', + ); + } else { + prefs.remove(kFeaturedPostsCollapsedId); + debugPrint( + 'PostFeaturedList: Removed stored collapsed ID.', + ); + } + }, + icon: Icon( + isCollapsed.value + ? Symbols.expand_more + : Symbols.expand_less, + ), + ), ], ).padding(horizontal: 16, vertical: 8), - featuredPostsAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stack) => Center(child: Text('Error: $error')), - data: (posts) { - return SizedBox( - height: 320, - child: PageView.builder( - controller: pageViewController, - scrollDirection: Axis.horizontal, - itemCount: posts.length, - itemBuilder: (context, index) { - return SingleChildScrollView( - child: PostActionableItem( - item: posts[index], - borderRadius: 8, - ), - ); - }, - ), - ); - }, + AnimatedSize( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + child: Visibility( + visible: !isCollapsed.value, + child: featuredPostsAsync.when( + loading: + () => const Center(child: CircularProgressIndicator()), + error: (error, stack) => Center(child: Text('Error: $error')), + data: (posts) { + return SizedBox( + height: 320, + child: PageView.builder( + controller: pageViewController, + scrollDirection: Axis.horizontal, + itemCount: posts.length, + itemBuilder: (context, index) { + return SingleChildScrollView( + child: PostActionableItem( + item: posts[index], + borderRadius: 8, + ), + ); + }, + ), + ); + }, + ), + ), ), ], ),