Basic posting

This commit is contained in:
2025-04-26 01:47:47 +08:00
parent 7bf4f9ef47
commit a564e4ee0a
13 changed files with 216 additions and 87 deletions

View File

@ -14,7 +14,6 @@ class TabsScreen extends StatelessWidget {
builder: (context, child, _) {
final tabsRouter = AutoTabsRouter.of(context);
return Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
backgroundColor: Colors.transparent,
body: child,

View File

@ -1,9 +1,11 @@
import 'package:auto_route/annotations.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:island/route.gr.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/models/post.dart';
import 'package:island/widgets/post/post_item.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
import 'package:dio/dio.dart';
import 'package:island/pods/network.dart';
@ -18,10 +20,24 @@ class ExploreScreen extends ConsumerWidget {
return AppScaffold(
appBar: AppBar(title: const Text('Explore')),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.router.push(PostComposeRoute()).then((value) {
if (value != null) {
ref.invalidate(postListProvider);
}
});
},
child: const Icon(LucideIcons.pencil),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
body: postAsync.when(
data:
(controller) => RefreshIndicator(
onRefresh: controller.refresh,
onRefresh:
() => Future.sync((() {
ref.invalidate(postListProvider);
})),
child: InfiniteList(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom,
@ -44,7 +60,7 @@ class ExploreScreen extends ConsumerWidget {
child: Text('Error: $e', textAlign: TextAlign.center),
),
onTap: () {
postAsync.value?.refresh();
ref.invalidate(postListProvider);
},
),
),
@ -70,13 +86,6 @@ class _PostListController {
final int take = 20;
int total = 0;
Future<void> refresh() async {
hasReachedMax = false;
offset = 0;
posts.clear();
await fetchMore();
}
Future<void> fetchMore() async {
if (isLoading || hasReachedMax) return;
isLoading = true;

View File

@ -0,0 +1,97 @@
import 'package:auto_route/annotations.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/pods/network.dart';
import 'package:island/screens/account/me/publishers.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:styled_widget/styled_widget.dart';
@RoutePage()
class PostComposeScreen extends HookConsumerWidget {
const PostComposeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final publishers = ref.watch(publishersManagedProvider);
final currentPublisher = useState<SnPublisher?>(null);
useEffect(() {
if (publishers.value?.isNotEmpty ?? false) {
currentPublisher.value = publishers.value!.first;
}
return null;
}, [publishers]);
final contentController = useTextEditingController();
final submitting = useState(false);
Future<void> performAction() async {
if (!contentController.text.isNotEmpty) {
return;
}
try {
submitting.value = true;
final client = ref.watch(apiClientProvider);
await client.post('/posts', data: {'content': contentController.text});
if (context.mounted) {
context.maybePop(true);
}
} catch (err) {
showErrorAlert(err);
} finally {
submitting.value = false;
}
}
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
actions: [
IconButton(
onPressed: submitting.value ? null : performAction,
icon: const Icon(LucideIcons.upload),
),
const Gap(8),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Row(
spacing: 12,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ProfilePictureWidget(
item: currentPublisher.value?.picture,
radius: 24,
),
Expanded(
child: TextField(
controller: contentController,
decoration: InputDecoration.collapsed(
hintText: 'What\'s happened?!',
),
maxLines: null,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
),
],
).padding(all: 16),
),
],
),
);
}
}