✨ Auto collapse featured post if read
This commit is contained in:
@@ -23,6 +23,8 @@ const kAppSoundEffects = 'app_sound_effects';
|
|||||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||||
const kAppWindowSize = 'app_window_size';
|
const kAppWindowSize = 'app_window_size';
|
||||||
const kAppEnterToSend = 'app_enter_to_send';
|
const kAppEnterToSend = 'app_enter_to_send';
|
||||||
|
const kFeaturedPostsCollapsedId =
|
||||||
|
'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post
|
||||||
|
|
||||||
const Map<String, FilterQuality> kImageQualityLevel = {
|
const Map<String, FilterQuality> kImageQualityLevel = {
|
||||||
'settingsImageQualityLowest': FilterQuality.none,
|
'settingsImageQualityLowest': FilterQuality.none,
|
||||||
|
@@ -7,6 +7,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:styled_widget/styled_widget.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';
|
part 'post_featured.g.dart';
|
||||||
|
|
||||||
@@ -25,7 +26,13 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
final featuredPostsAsync = ref.watch(featuredPostsProvider);
|
final featuredPostsAsync = ref.watch(featuredPostsProvider);
|
||||||
|
|
||||||
final pageViewController = usePageController();
|
final pageViewController = usePageController();
|
||||||
|
final prefs = ref.watch(sharedPreferencesProvider);
|
||||||
final pageViewCurrent = useState(0);
|
final pageViewCurrent = useState(0);
|
||||||
|
final previousFirstPostId = useState<String?>(null);
|
||||||
|
final storedCollapsedId = useState<String?>(
|
||||||
|
prefs.getString(kFeaturedPostsCollapsedId),
|
||||||
|
);
|
||||||
|
final isCollapsed = useState(false);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
pageViewController.addListener(() {
|
pageViewController.addListener(() {
|
||||||
@@ -34,6 +41,59 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
return null;
|
return null;
|
||||||
}, [pageViewController]);
|
}, [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(
|
return ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: Card(
|
child: Card(
|
||||||
@@ -73,29 +133,69 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Symbols.arrow_right),
|
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),
|
).padding(horizontal: 16, vertical: 8),
|
||||||
featuredPostsAsync.when(
|
AnimatedSize(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
duration: const Duration(milliseconds: 300),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
curve: Curves.easeInOut,
|
||||||
data: (posts) {
|
child: Visibility(
|
||||||
return SizedBox(
|
visible: !isCollapsed.value,
|
||||||
height: 320,
|
child: featuredPostsAsync.when(
|
||||||
child: PageView.builder(
|
loading:
|
||||||
controller: pageViewController,
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
scrollDirection: Axis.horizontal,
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
itemCount: posts.length,
|
data: (posts) {
|
||||||
itemBuilder: (context, index) {
|
return SizedBox(
|
||||||
return SingleChildScrollView(
|
height: 320,
|
||||||
child: PostActionableItem(
|
child: PageView.builder(
|
||||||
item: posts[index],
|
controller: pageViewController,
|
||||||
borderRadius: 8,
|
scrollDirection: Axis.horizontal,
|
||||||
),
|
itemCount: posts.length,
|
||||||
);
|
itemBuilder: (context, index) {
|
||||||
},
|
return SingleChildScrollView(
|
||||||
),
|
child: PostActionableItem(
|
||||||
);
|
item: posts[index],
|
||||||
},
|
borderRadius: 8,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user