192 lines
6.7 KiB
Dart
192 lines
6.7 KiB
Dart
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:island/pods/post/post_list.dart';
|
|
import 'package:island/widgets/app_scaffold.dart';
|
|
import 'package:island/widgets/post/post_item.dart';
|
|
|
|
const kShufflePostListId = 'shuffle';
|
|
|
|
class _ShufflePageNotifier extends Notifier<int> {
|
|
@override
|
|
int build() => 0;
|
|
|
|
void updatePage(int page) => state = page;
|
|
}
|
|
|
|
final _shufflePageProvider = NotifierProvider<_ShufflePageNotifier, int>(
|
|
_ShufflePageNotifier.new,
|
|
);
|
|
|
|
class PostShuffleScreen extends HookConsumerWidget {
|
|
const PostShuffleScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
const query = PostListQuery(shuffle: true);
|
|
final cfg = PostListQueryConfig(
|
|
id: kShufflePostListId,
|
|
initialFilter: query,
|
|
);
|
|
final postListState = ref.watch(postListProvider(cfg));
|
|
final postListNotifier = ref.watch(postListProvider(cfg).notifier);
|
|
|
|
final savedPage = ref.watch(_shufflePageProvider);
|
|
final pageNotifier = ref.watch(_shufflePageProvider.notifier);
|
|
|
|
final pageController = usePageController(initialPage: savedPage);
|
|
|
|
useEffect(() {
|
|
return pageController.dispose;
|
|
}, []);
|
|
|
|
final items = postListState.value?.items ?? [];
|
|
|
|
useEffect(() {
|
|
void listener() {
|
|
if (!pageController.hasClients) return;
|
|
final page = pageController.page?.round() ?? 0;
|
|
if (page != savedPage) {
|
|
pageNotifier.updatePage(page);
|
|
}
|
|
if (page >= items.length - 3 && !postListNotifier.fetchedAll) {
|
|
postListNotifier.fetchFurther();
|
|
}
|
|
}
|
|
|
|
pageController.addListener(listener);
|
|
return () => pageController.removeListener(listener);
|
|
}, [items.length, postListNotifier.fetchedAll]);
|
|
|
|
return AppScaffold(
|
|
appBar: AppBar(title: const Text('postShuffle').tr()),
|
|
body: Builder(
|
|
builder: (context) {
|
|
if (items.isEmpty) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
return Stack(
|
|
children: [
|
|
PageView.builder(
|
|
controller: pageController,
|
|
scrollDirection: Axis.vertical,
|
|
itemCount: items.length,
|
|
itemBuilder: (context, index) {
|
|
return SingleChildScrollView(
|
|
child: PostActionableItem(
|
|
item: items[index],
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 8,
|
|
vertical: 8,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
Positioned(
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Colors.transparent,
|
|
Colors.black.withOpacity(0.3),
|
|
],
|
|
),
|
|
),
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
top: 12,
|
|
bottom: 16,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
IconButton(
|
|
onPressed: () {
|
|
final currentPage = pageController.page?.round() ?? 0;
|
|
if (currentPage > 0) {
|
|
pageController.animateToPage(
|
|
currentPage - 1,
|
|
duration: const Duration(milliseconds: 300),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
}
|
|
},
|
|
icon: Icon(
|
|
Icons.keyboard_double_arrow_up,
|
|
color: Colors.white.withOpacity(0.8),
|
|
size: 20,
|
|
shadows: [
|
|
Shadow(
|
|
offset: const Offset(0, 2),
|
|
blurRadius: 4,
|
|
color: Colors.black.withOpacity(0.5),
|
|
),
|
|
],
|
|
),
|
|
padding: EdgeInsets.zero,
|
|
constraints: const BoxConstraints(),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
'swipeToExplore'.tr(),
|
|
style: TextStyle(
|
|
color: Colors.white.withOpacity(0.9),
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w500,
|
|
shadows: [
|
|
Shadow(
|
|
offset: const Offset(0, 2),
|
|
blurRadius: 4,
|
|
color: Colors.black.withOpacity(0.5),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
IconButton(
|
|
onPressed: () {
|
|
final currentPage = pageController.page?.round() ?? 0;
|
|
if (currentPage < items.length - 1) {
|
|
pageController.animateToPage(
|
|
currentPage + 1,
|
|
duration: const Duration(milliseconds: 300),
|
|
curve: Curves.easeInOut,
|
|
);
|
|
}
|
|
},
|
|
icon: Icon(
|
|
Icons.keyboard_double_arrow_down,
|
|
color: Colors.white.withOpacity(0.8),
|
|
size: 20,
|
|
shadows: [
|
|
Shadow(
|
|
offset: const Offset(0, 2),
|
|
blurRadius: 4,
|
|
color: Colors.black.withOpacity(0.5),
|
|
),
|
|
],
|
|
),
|
|
padding: EdgeInsets.zero,
|
|
constraints: const BoxConstraints(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|