2024-09-12 16:17:56 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
2024-05-18 10:17:16 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2024-09-07 09:45:44 +00:00
|
|
|
import 'package:gap/gap.dart';
|
2024-05-18 10:17:16 +00:00
|
|
|
import 'package:get/get.dart';
|
2024-07-25 06:42:50 +00:00
|
|
|
import 'package:solian/controllers/post_list_controller.dart';
|
2024-05-19 10:01:00 +00:00
|
|
|
import 'package:solian/providers/auth.dart';
|
2024-09-12 16:17:56 +00:00
|
|
|
import 'package:solian/providers/navigation.dart';
|
2024-05-19 10:01:00 +00:00
|
|
|
import 'package:solian/router.dart';
|
2024-05-25 05:00:40 +00:00
|
|
|
import 'package:solian/screens/account/notification.dart';
|
|
|
|
import 'package:solian/theme.dart';
|
2024-08-18 16:33:03 +00:00
|
|
|
import 'package:solian/widgets/account/signin_required_overlay.dart';
|
2024-06-06 12:23:50 +00:00
|
|
|
import 'package:solian/widgets/current_state_action.dart';
|
2024-07-12 14:31:45 +00:00
|
|
|
import 'package:solian/widgets/app_bar_leading.dart';
|
2024-10-05 06:25:57 +00:00
|
|
|
import 'package:solian/widgets/navigation/realm_switcher.dart';
|
2024-07-25 08:08:46 +00:00
|
|
|
import 'package:solian/widgets/posts/post_shuffle_swiper.dart';
|
2024-07-31 17:21:27 +00:00
|
|
|
import 'package:solian/widgets/posts/post_warped_list.dart';
|
2024-05-18 10:17:16 +00:00
|
|
|
|
2024-09-23 14:43:13 +00:00
|
|
|
class ExploreScreen extends StatefulWidget {
|
|
|
|
const ExploreScreen({super.key});
|
2024-05-18 10:17:16 +00:00
|
|
|
|
|
|
|
@override
|
2024-09-23 14:43:13 +00:00
|
|
|
State<ExploreScreen> createState() => _ExploreScreenState();
|
2024-05-18 10:17:16 +00:00
|
|
|
}
|
|
|
|
|
2024-09-23 14:43:13 +00:00
|
|
|
class _ExploreScreenState extends State<ExploreScreen>
|
2024-07-24 18:00:29 +00:00
|
|
|
with SingleTickerProviderStateMixin {
|
2024-07-25 08:08:46 +00:00
|
|
|
late final PostListController _postController;
|
2024-07-24 18:00:29 +00:00
|
|
|
late final TabController _tabController;
|
|
|
|
|
2024-09-12 16:17:56 +00:00
|
|
|
List<StreamSubscription>? _subscriptions;
|
|
|
|
|
2024-05-18 10:17:16 +00:00
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
2024-09-12 16:17:56 +00:00
|
|
|
final navState = Get.find<NavigationStateProvider>();
|
2024-07-26 06:21:00 +00:00
|
|
|
_postController = PostListController();
|
2024-09-12 16:17:56 +00:00
|
|
|
_postController.realm = navState.focusedRealm.value?.alias;
|
2024-08-18 16:33:03 +00:00
|
|
|
_tabController = TabController(length: 3, vsync: this);
|
2024-07-24 18:00:29 +00:00
|
|
|
_tabController.addListener(() {
|
2024-08-18 16:33:03 +00:00
|
|
|
if (_postController.mode.value == _tabController.index) return;
|
|
|
|
_postController.mode.value = _tabController.index;
|
|
|
|
_postController.reloadAllOver();
|
2024-07-24 18:00:29 +00:00
|
|
|
});
|
2024-09-12 16:17:56 +00:00
|
|
|
_subscriptions = [
|
|
|
|
Get.find<NavigationStateProvider>().focusedRealm.listen((value) {
|
|
|
|
if (value?.alias != _postController.realm) {
|
|
|
|
_postController.realm = value?.alias;
|
|
|
|
_postController.reloadAllOver();
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
];
|
2024-05-18 10:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-08-18 16:33:03 +00:00
|
|
|
final AuthProvider auth = Get.find();
|
|
|
|
|
2024-07-24 17:43:50 +00:00
|
|
|
return Material(
|
|
|
|
color: Theme.of(context).colorScheme.surface,
|
2024-07-25 17:16:32 +00:00
|
|
|
child: Scaffold(
|
|
|
|
floatingActionButton: FloatingActionButton(
|
|
|
|
child: const Icon(Icons.add),
|
2024-08-04 10:13:59 +00:00
|
|
|
onPressed: () async {
|
|
|
|
final value = await showModalBottomSheet(
|
2024-07-25 17:16:32 +00:00
|
|
|
useRootNavigator: true,
|
|
|
|
isScrollControlled: true,
|
|
|
|
context: context,
|
2024-08-04 10:13:59 +00:00
|
|
|
builder: (context) => const PostCreatePopup(),
|
2024-07-25 17:16:32 +00:00
|
|
|
);
|
2024-08-04 10:13:59 +00:00
|
|
|
if (value is Future) {
|
|
|
|
value.then((_) {
|
|
|
|
_postController.reloadAllOver();
|
|
|
|
});
|
|
|
|
} else if (value != null) {
|
|
|
|
_postController.reloadAllOver();
|
|
|
|
}
|
2024-07-25 17:16:32 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
body: NestedScrollView(
|
|
|
|
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
|
|
|
return [
|
|
|
|
SliverAppBar(
|
2024-10-05 06:25:57 +00:00
|
|
|
flexibleSpace: SizedBox(
|
|
|
|
height: 48,
|
|
|
|
child: const Row(
|
|
|
|
children: [
|
|
|
|
RealmSwitcher(),
|
|
|
|
],
|
|
|
|
).paddingSymmetric(horizontal: 8),
|
|
|
|
).paddingOnly(top: MediaQuery.of(context).padding.top),
|
2024-07-25 17:16:32 +00:00
|
|
|
floating: true,
|
2024-09-13 12:22:10 +00:00
|
|
|
toolbarHeight: AppTheme.toolbarHeight(context),
|
2024-07-25 17:16:32 +00:00
|
|
|
leading: AppBarLeadingButton.adaptive(context),
|
|
|
|
actions: [
|
|
|
|
const BackgroundStateWidget(),
|
|
|
|
const NotificationButton(),
|
|
|
|
SizedBox(
|
2024-09-13 12:22:10 +00:00
|
|
|
width: AppTheme.isLargeScreen(context) ? 8 : 16,
|
2024-07-25 08:08:46 +00:00
|
|
|
),
|
2024-07-25 06:42:50 +00:00
|
|
|
],
|
2024-07-25 17:16:32 +00:00
|
|
|
bottom: TabBar(
|
|
|
|
controller: _tabController,
|
|
|
|
tabs: [
|
|
|
|
Tab(text: 'postListNews'.tr),
|
2024-08-18 16:33:03 +00:00
|
|
|
Tab(text: 'postListFriends'.tr),
|
2024-07-25 17:16:32 +00:00
|
|
|
Tab(text: 'postListShuffle'.tr),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
];
|
|
|
|
},
|
|
|
|
body: Obx(() {
|
|
|
|
if (_postController.isPreparing.isTrue) {
|
|
|
|
return const Center(
|
|
|
|
child: CircularProgressIndicator(),
|
2024-07-25 08:08:46 +00:00
|
|
|
);
|
2024-07-25 17:16:32 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 16:17:56 +00:00
|
|
|
return Column(
|
2024-07-25 17:16:32 +00:00
|
|
|
children: [
|
2024-09-12 16:17:56 +00:00
|
|
|
Expanded(
|
|
|
|
child: TabBarView(
|
|
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
|
|
controller: _tabController,
|
|
|
|
children: [
|
|
|
|
RefreshIndicator(
|
|
|
|
onRefresh: () => _postController.reloadAllOver(),
|
|
|
|
child: CustomScrollView(slivers: [
|
|
|
|
PostWarpedListWidget(
|
|
|
|
controller: _postController.pagingController,
|
|
|
|
onUpdate: () => _postController.reloadAllOver(),
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
),
|
|
|
|
Obx(() {
|
|
|
|
if (auth.isAuthorized.value) {
|
|
|
|
return RefreshIndicator(
|
|
|
|
onRefresh: () => _postController.reloadAllOver(),
|
|
|
|
child: CustomScrollView(slivers: [
|
|
|
|
PostWarpedListWidget(
|
|
|
|
controller: _postController.pagingController,
|
|
|
|
onUpdate: () => _postController.reloadAllOver(),
|
|
|
|
),
|
|
|
|
]),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
return SigninRequiredOverlay(
|
2024-09-15 15:32:15 +00:00
|
|
|
onDone: () => _postController.reloadAllOver(),
|
2024-09-12 16:17:56 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
PostShuffleSwiper(controller: _postController),
|
|
|
|
],
|
|
|
|
),
|
2024-07-25 17:16:32 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}),
|
2024-05-18 16:56:32 +00:00
|
|
|
),
|
2024-05-18 10:17:16 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
2024-07-09 14:39:44 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
2024-07-25 06:42:50 +00:00
|
|
|
_postController.dispose();
|
2024-09-12 16:17:56 +00:00
|
|
|
if (_subscriptions != null) {
|
|
|
|
for (final subscription in _subscriptions!) {
|
|
|
|
subscription.cancel();
|
|
|
|
}
|
|
|
|
}
|
2024-07-09 14:39:44 +00:00
|
|
|
super.dispose();
|
|
|
|
}
|
2024-05-18 10:17:16 +00:00
|
|
|
}
|
2024-07-06 12:55:53 +00:00
|
|
|
|
2024-07-24 17:43:50 +00:00
|
|
|
class PostCreatePopup extends StatelessWidget {
|
2024-07-09 14:39:44 +00:00
|
|
|
final bool hideDraftBox;
|
2024-07-06 19:02:10 +00:00
|
|
|
|
2024-07-24 17:43:50 +00:00
|
|
|
const PostCreatePopup({
|
2024-07-09 14:39:44 +00:00
|
|
|
super.key,
|
|
|
|
this.hideDraftBox = false,
|
|
|
|
});
|
2024-07-06 12:55:53 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final AuthProvider auth = Get.find();
|
|
|
|
|
2024-07-24 17:18:47 +00:00
|
|
|
if (auth.isAuthorized.isFalse) {
|
2024-09-07 09:48:07 +00:00
|
|
|
return const SizedBox.shrink();
|
2024-07-24 17:18:47 +00:00
|
|
|
}
|
|
|
|
|
2024-07-24 17:43:50 +00:00
|
|
|
final List<dynamic> actionList = [
|
|
|
|
(
|
2024-07-30 08:53:13 +00:00
|
|
|
icon: const Icon(Icons.post_add),
|
2024-07-30 03:50:26 +00:00
|
|
|
label: 'postEditorModeStory'.tr,
|
2024-07-24 17:43:50 +00:00
|
|
|
onTap: () {
|
2024-08-04 10:13:59 +00:00
|
|
|
Navigator.pop(
|
|
|
|
context,
|
|
|
|
AppRouter.instance.pushNamed(
|
|
|
|
'postEditor',
|
|
|
|
queryParameters: {
|
|
|
|
'mode': 0.toString(),
|
|
|
|
},
|
|
|
|
),
|
2024-08-01 17:00:31 +00:00
|
|
|
);
|
2024-07-30 08:53:13 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
icon: const Icon(Icons.description),
|
|
|
|
label: 'postEditorModeArticle'.tr,
|
|
|
|
onTap: () {
|
2024-08-04 10:13:59 +00:00
|
|
|
Navigator.pop(
|
|
|
|
context,
|
|
|
|
AppRouter.instance.pushNamed(
|
|
|
|
'postEditor',
|
|
|
|
queryParameters: {
|
|
|
|
'mode': 1.toString(),
|
|
|
|
},
|
|
|
|
),
|
2024-08-01 17:00:31 +00:00
|
|
|
);
|
2024-07-24 17:43:50 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
(
|
|
|
|
icon: const Icon(Icons.drafts),
|
|
|
|
label: 'draftBoxOpen'.tr,
|
|
|
|
onTap: () {
|
2024-08-04 10:13:59 +00:00
|
|
|
Navigator.pop(
|
|
|
|
context,
|
|
|
|
AppRouter.instance.pushNamed('draftBox'),
|
|
|
|
);
|
2024-07-24 17:43:50 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
];
|
|
|
|
|
|
|
|
return SizedBox(
|
2024-07-27 11:20:53 +00:00
|
|
|
height: MediaQuery.of(context).size.height * 0.38,
|
2024-07-24 17:43:50 +00:00
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
'postNew'.tr,
|
|
|
|
style: Theme.of(context).textTheme.headlineSmall,
|
|
|
|
).paddingOnly(left: 24, right: 24, top: 32, bottom: 16),
|
|
|
|
Expanded(
|
|
|
|
child: GridView.count(
|
|
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
|
|
crossAxisCount: 3,
|
|
|
|
children: actionList
|
|
|
|
.map((x) => Card(
|
|
|
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
|
|
child: InkWell(
|
|
|
|
borderRadius:
|
|
|
|
const BorderRadius.all(Radius.circular(8)),
|
|
|
|
onTap: x.onTap,
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
x.icon,
|
2024-09-07 09:45:44 +00:00
|
|
|
const Gap(8),
|
2024-08-10 17:57:58 +00:00
|
|
|
Expanded(
|
|
|
|
child: Text(
|
|
|
|
x.label,
|
|
|
|
overflow: TextOverflow.fade,
|
|
|
|
),
|
|
|
|
),
|
2024-07-24 17:43:50 +00:00
|
|
|
],
|
|
|
|
).paddingAll(18),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
.toList(),
|
|
|
|
).paddingSymmetric(horizontal: 20),
|
2024-07-24 17:18:47 +00:00
|
|
|
),
|
2024-07-24 17:43:50 +00:00
|
|
|
],
|
|
|
|
),
|
2024-07-24 17:18:47 +00:00
|
|
|
);
|
2024-07-06 12:55:53 +00:00
|
|
|
}
|
|
|
|
}
|