From 05425da913dd4d38174dcc93cf88f18fe1febb73 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 10 Nov 2024 01:34:58 +0800 Subject: [PATCH] :sparkles: Post new fab --- assets/translations/en-US.json | 4 +- assets/translations/zh-CN.json | 4 +- lib/router.dart | 13 ++++ lib/screens/explore.dart | 78 ++++++++++++++++++++++++ lib/screens/post/post_editor.dart | 10 +++ lib/widgets/navigation/app_scaffold.dart | 6 ++ pubspec.lock | 8 +++ pubspec.yaml | 1 + 8 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 lib/screens/post/post_editor.dart diff --git a/assets/translations/en-US.json b/assets/translations/en-US.json index 2a70256..4f6f814 100644 --- a/assets/translations/en-US.json +++ b/assets/translations/en-US.json @@ -64,5 +64,7 @@ "accountProfileEditApplied": "Profile modification applied.", "publishersNew": "New Publisher", "publisherNewSubtitle": "Create a new publisher identity.", - "publisherSyncWithAccount": "Sync with account" + "publisherSyncWithAccount": "Sync with account", + "writePostTypeStory": "Post a story", + "writePostTypeArticle": "Write an article" } diff --git a/assets/translations/zh-CN.json b/assets/translations/zh-CN.json index 6c42db4..43abfb0 100644 --- a/assets/translations/zh-CN.json +++ b/assets/translations/zh-CN.json @@ -64,5 +64,7 @@ "accountProfileEditApplied": "个人资料修改已被应用。", "publishersNew": "新发布者", "publisherNewSubtitle": "创建一个新的公共身份。", - "publisherSyncWithAccount": "同步账户信息" + "publisherSyncWithAccount": "同步账户信息", + "writePostTypeStory": "发动态", + "writePostTypeArticle": "写文章" } diff --git a/lib/router.dart b/lib/router.dart index 6ea6d7c..f31212f 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -8,6 +8,7 @@ import 'package:surface/screens/auth/login.dart'; import 'package:surface/screens/auth/register.dart'; import 'package:surface/screens/explore.dart'; import 'package:surface/screens/home.dart'; +import 'package:surface/screens/post/post_editor.dart'; import 'package:surface/widgets/navigation/app_scaffold.dart'; final appRouter = GoRouter( @@ -35,6 +36,18 @@ final appRouter = GoRouter( ), ], ), + ShellRoute( + builder: (context, state, child) => AppScaffold( + body: child, + ), + routes: [ + GoRoute( + path: '/post/write/:mode', + name: 'postEditor', + builder: (context, state) => const PostEditorScreen(), + ), + ], + ), ShellRoute( builder: (context, state, child) => AppScaffold( body: child, diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index 6ac5ed5..2db425d 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -1,5 +1,9 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; +import 'package:gap/gap.dart'; +import 'package:go_router/go_router.dart'; +import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; import 'package:surface/providers/sn_attachment.dart'; import 'package:surface/providers/sn_network.dart'; @@ -16,6 +20,8 @@ class ExploreScreen extends StatefulWidget { } class _ExploreScreenState extends State { + final _fabKey = GlobalKey(); + bool _isBusy = true; final List _posts = List.empty(growable: true); @@ -72,6 +78,78 @@ class _ExploreScreenState extends State { appBar: AppBar( title: Text('screenExplore').tr(), ), + floatingActionButtonLocation: ExpandableFab.location, + floatingActionButton: ExpandableFab( + key: _fabKey, + distance: 75, + type: ExpandableFabType.up, + childrenAnimation: ExpandableFabAnimation.none, + overlayStyle: ExpandableFabOverlayStyle(blur: 10), + openButtonBuilder: RotateFloatingActionButtonBuilder( + child: const Icon(Symbols.add, size: 28), + fabSize: ExpandableFabSize.regular, + foregroundColor: + Theme.of(context).floatingActionButtonTheme.foregroundColor, + backgroundColor: + Theme.of(context).floatingActionButtonTheme.backgroundColor, + shape: const CircleBorder(), + ), + closeButtonBuilder: DefaultFloatingActionButtonBuilder( + child: const Icon(Symbols.close, size: 28), + fabSize: ExpandableFabSize.regular, + foregroundColor: + Theme.of(context).floatingActionButtonTheme.foregroundColor, + backgroundColor: + Theme.of(context).floatingActionButtonTheme.backgroundColor, + shape: const CircleBorder(), + ), + children: [ + Row( + children: [ + Text('writePostTypeStory').tr(), + const Gap(20), + FloatingActionButton( + heroTag: null, + tooltip: 'writePostTypeStory'.tr(), + onPressed: () { + GoRouter.of(context).pushNamed('postEditor', pathParameters: { + 'mode': 'story', + }).then((value) { + if (value == true) { + _posts.clear(); + _fetchPosts(); + } + }); + _fabKey.currentState!.toggle(); + }, + child: const Icon(Symbols.post_rounded), + ), + ], + ), + Row( + children: [ + Text('writePostTypeArticle').tr(), + const Gap(20), + FloatingActionButton( + heroTag: null, + tooltip: 'writePostTypeArticle'.tr(), + onPressed: () { + GoRouter.of(context).pushNamed('postEditor', pathParameters: { + 'mode': 'article', + }).then((value) { + if (value == true) { + _posts.clear(); + _fetchPosts(); + } + }); + _fabKey.currentState!.toggle(); + }, + child: const Icon(Symbols.news), + ), + ], + ), + ], + ), body: InfiniteList( itemCount: _posts.length, isLoading: _isBusy, diff --git a/lib/screens/post/post_editor.dart b/lib/screens/post/post_editor.dart new file mode 100644 index 0000000..466622a --- /dev/null +++ b/lib/screens/post/post_editor.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class PostEditorScreen extends StatelessWidget { + const PostEditorScreen({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/widgets/navigation/app_scaffold.dart b/lib/widgets/navigation/app_scaffold.dart index 5b7f34f..302f4d3 100644 --- a/lib/widgets/navigation/app_scaffold.dart +++ b/lib/widgets/navigation/app_scaffold.dart @@ -8,6 +8,8 @@ import 'package:surface/widgets/navigation/app_bottom_navigation.dart'; class AppScaffold extends StatelessWidget { final PreferredSizeWidget? appBar; + final FloatingActionButtonLocation? floatingActionButtonLocation; + final Widget? floatingActionButton; final String? title; final Widget? body; final bool autoImplyAppBar; @@ -15,6 +17,8 @@ class AppScaffold extends StatelessWidget { const AppScaffold({ super.key, this.appBar, + this.floatingActionButton, + this.floatingActionButtonLocation, this.title, this.body, this.autoImplyAppBar = false, @@ -44,6 +48,8 @@ class AppScaffold extends StatelessWidget { : null) : null), body: body, + floatingActionButtonLocation: floatingActionButtonLocation, + floatingActionButton: floatingActionButton, bottomNavigationBar: isShowBottomNavigation ? AppBottomNavigationBar() : null, ), diff --git a/pubspec.lock b/pubspec.lock index c1d952c..9d7c8a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -459,6 +459,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" + flutter_expandable_fab: + dependency: "direct main" + description: + name: flutter_expandable_fab + sha256: "85275279d19faf4fbe5639dc1f139b4555b150e079d056f085601a45688af12c" + url: "https://pub.dev" + source: hosted + version: "2.3.0" flutter_image_compress: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index de6553a..43cb93a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: file_picker: ^8.1.3 flutter_image_compress: ^2.3.0 croppy: ^1.3.1 + flutter_expandable_fab: ^2.3.0 dev_dependencies: flutter_test: