From 0d5a16e4475dec25c0c6d2e29b43013374883104 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 12 Oct 2021 16:58:05 +0800 Subject: [PATCH] [flutter]: config menu trash ui --- .../domain/page_stack/page_stack.dart | 38 ++++++--------- app_flowy/lib/workspace/domain/view_ext.dart | 30 ++++++++++++ .../presentation/home/navigation.dart | 23 ++++----- .../stack_page/blank/blank_page.dart | 9 ++-- .../stack_page/doc/doc_stack_page.dart | 6 ++- .../presentation/stack_page/trash_page.dart | 47 +++++++++++++++++++ .../presentation/widgets/menu/menu.dart | 39 ++++++--------- .../widgets/menu/widget/app/section/item.dart | 3 +- .../widgets/menu/widget/menu_trash.dart | 33 +++++++++++++ .../widgets/menu/widget/menu_user.dart | 5 +- 10 files changed, 162 insertions(+), 71 deletions(-) create mode 100644 app_flowy/lib/workspace/domain/view_ext.dart create mode 100644 app_flowy/lib/workspace/presentation/stack_page/trash_page.dart create mode 100644 app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart diff --git a/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index db105d4cf5..4e2159d53a 100644 --- a/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -1,18 +1,15 @@ import 'package:equatable/equatable.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; - import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart'; import 'package:app_flowy/workspace/presentation/widgets/prelude.dart'; typedef NavigationCallback = void Function(String id); abstract class NavigationItem { - String get title; + Widget get titleWidget; String get identifier; NavigationCallback get action => (id) { @@ -20,33 +17,28 @@ abstract class NavigationItem { }; } +enum HomeStackType { + blank, + doc, + trash, +} + +List pages = HomeStackType.values.toList(); + abstract class HomeStackContext extends Equatable with NavigationItem { List get navigationItems; @override - String get title; + Widget get titleWidget; @override String get identifier; - ViewType get type; + HomeStackType get type; Widget render(); } -extension ViewStackContext on View { - HomeStackContext intoStackContext() { - switch (viewType) { - case ViewType.Blank: - return BlankStackContext(); - case ViewType.Doc: - return DocStackContext(view: this); - default: - return BlankStackContext(); - } - } -} - class HomeStackNotifier extends ChangeNotifier { HomeStackContext inner; HomeStackNotifier({HomeStackContext? context}) : inner = context ?? BlankStackContext(); @@ -64,8 +56,8 @@ class HomeStackManager { final HomeStackNotifier _notifier = HomeStackNotifier(); HomeStackManager(); - String title() { - return _notifier.context.title; + Widget title() { + return _notifier.context.titleWidget; } void setStack(HomeStackContext context) { @@ -93,7 +85,7 @@ class HomeStackManager { child: Consumer(builder: (ctx, HomeStackNotifier notifier, child) { return FadingIndexedStack( index: pages.indexOf(notifier.context.type), - children: ViewType.values.map((viewType) { + children: HomeStackType.values.map((viewType) { if (viewType == notifier.context.type) { return notifier.context.render(); } else { @@ -105,5 +97,3 @@ class HomeStackManager { ); } } - -List pages = ViewType.values.toList(); diff --git a/app_flowy/lib/workspace/domain/view_ext.dart b/app_flowy/lib/workspace/domain/view_ext.dart new file mode 100644 index 0000000000..4523531037 --- /dev/null +++ b/app_flowy/lib/workspace/domain/view_ext.dart @@ -0,0 +1,30 @@ +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; +import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; + +extension ToHomeStackContext on View { + HomeStackContext stackContext() { + switch (viewType) { + case ViewType.Blank: + return BlankStackContext(); + case ViewType.Doc: + return DocStackContext(view: this); + default: + return BlankStackContext(); + } + } +} + +extension ToHomeStackType on View { + HomeStackType stackType() { + switch (viewType) { + case ViewType.Blank: + return HomeStackType.blank; + case ViewType.Doc: + return HomeStackType.doc; + default: + return HomeStackType.blank; + } + } +} diff --git a/app_flowy/lib/workspace/presentation/home/navigation.dart b/app_flowy/lib/workspace/presentation/home/navigation.dart index 589beac57f..3e68ca87ae 100644 --- a/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text_button.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -94,14 +95,12 @@ class IconNaviItemWidget extends StatelessWidget { Widget build(BuildContext context) { return SizedBox( height: 24, - child: FlowyTextButton( - item.title, - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - fontSize: 12, - onPressed: () { + child: InkWell( + child: item.titleWidget, + onTap: () { debugPrint('show app document'); }, - ), + ).padding(horizontal: 8, vertical: 2), ); } } @@ -114,14 +113,12 @@ class NaviItemWidget extends StatelessWidget { Widget build(BuildContext context) { return SizedBox( height: 24, - child: FlowyTextButton( - item.title, - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - fontSize: 12, - onPressed: () { + child: InkWell( + child: item.titleWidget, + onTap: () { debugPrint('show app document'); }, - ), + ).padding(horizontal: 8, vertical: 2), ); } } @@ -145,7 +142,7 @@ class EllipsisNaviItem extends NavigationItem { }); @override - String get title => "..."; + Widget get titleWidget => const FlowyText.medium('...'); @override NavigationCallback get action => (id) {}; diff --git a/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart b/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart index 5d6b3c06e1..fb62352b5a 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/blank/blank_page.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; @@ -10,10 +11,10 @@ class BlankStackContext extends HomeStackContext { List get props => ["1"]; @override - String get title => "Blank page"; + Widget get titleWidget => const FlowyText.medium('Blank page', fontSize: 12); @override - ViewType get type => ViewType.Blank; + HomeStackType get type => HomeStackType.blank; @override Widget render() { @@ -28,10 +29,10 @@ class BlankStackPage extends StatefulWidget { const BlankStackPage({Key? key}) : super(key: key); @override - State createState() => _AnnouncementPage(); + State createState() => _BlankStackPageState(); } -class _AnnouncementPage extends State { +class _BlankStackPageState extends State { @override Widget build(BuildContext context) { return SizedBox.expand( diff --git a/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 240122c933..48bee91713 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -1,6 +1,8 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/doc/doc_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/domain/view_ext.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; @@ -15,11 +17,11 @@ class DocStackContext extends HomeStackContext { DocStackContext({required View view, Key? key}) : _view = view; @override - String get title => _view.name; + Widget get titleWidget => FlowyText.medium(_view.name, fontSize: 12); @override String get identifier => _view.id; @override - ViewType get type => _view.viewType; + HomeStackType get type => _view.stackType(); @override List get props => [_view.id]; diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash_page.dart b/app_flowy/lib/workspace/presentation/stack_page/trash_page.dart new file mode 100644 index 0000000000..3e4b810fc9 --- /dev/null +++ b/app_flowy/lib/workspace/presentation/stack_page/trash_page.dart @@ -0,0 +1,47 @@ +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; + +class TrashStackContext extends HomeStackContext { + @override + String get identifier => "TrashStackContext"; + + @override + List get props => ["TrashStackContext"]; + + @override + Widget get titleWidget => const FlowyText.medium('Trash', fontSize: 12); + + @override + HomeStackType get type => HomeStackType.trash; + + @override + Widget render() { + return const TrashStackPage(); + } + + @override + List get navigationItems => [this]; +} + +class TrashStackPage extends StatefulWidget { + const TrashStackPage({Key? key}) : super(key: key); + + @override + State createState() => _TrashStackPageState(); +} + +class _TrashStackPageState extends State { + @override + Widget build(BuildContext context) { + return SizedBox.expand( + child: Container( + color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(10), + child: Container(), + ), + ), + ); + } +} diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart index ca4712c5be..6a668f6a02 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart @@ -18,6 +18,7 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/menu_user.d import 'widget/app/menu_app.dart'; import 'widget/app/create_button.dart'; +import 'widget/menu_trash.dart'; // [[diagram: HomeMenu's widget structure]] // get user profile or modify user @@ -101,6 +102,9 @@ class HomeMenu extends StatelessWidget { ], ).padding(horizontal: Insets.l), ), + const VSpace(20), + _renderTrash(context).padding(horizontal: Insets.l), + const VSpace(20), _renderNewAppButton(context), ], ), @@ -112,10 +116,10 @@ class HomeMenu extends StatelessWidget { builder: (context, state) { return state.map( initial: (_) => MenuList( - menuItems: menuItemsWithApps(context.read().state.apps), + menuItems: buildMenuItems(context.read().state.apps), ), loadApps: (s) => MenuList( - menuItems: menuItemsWithApps(some(s.apps)), + menuItems: buildMenuItems(some(s.apps)), ), loadFail: (s) => FlowyErrorPage(s.error.toString()), ); @@ -123,6 +127,10 @@ class HomeMenu extends StatelessWidget { ); } + Widget _renderTrash(BuildContext context) { + return const MenuTrash(); + } + Widget _renderNewAppButton(BuildContext context) { return NewAppButton( press: (appName) => context.read().add(MenuEvent.createApp(appName, desc: "")), @@ -133,31 +141,14 @@ class HomeMenu extends StatelessWidget { return const MenuTopBar(); } - List menuItemsWithApps(Option> someApps) { - return MenuItemBuilder().withUser(user).withApps(someApps).build(); - } -} - -class MenuItemBuilder { - List items = []; - - MenuItemBuilder(); - - MenuItemBuilder withUser(UserProfile user) { + List buildMenuItems(Option> apps) { + List items = []; items.add(MenuUser(user)); - return this; - } - MenuItemBuilder withApps(Option> someApps) { - List appWidgets = someApps.foldRight( - [], - (apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList(), - ); + List appWidgets = + apps.foldRight([], (apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList()); + items.addAll(appWidgets); - return this; - } - - List build() { return items; } } diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index 9d436c141a..78fe2fe5c6 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/view/view_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -44,7 +45,7 @@ class ViewSectionItem extends StatelessWidget { return InkWell( onTap: () { onSelected(context.read().state.view); - getIt().setStack(state.view.intoStackContext()); + getIt().setStack(state.view.stackContext()); }, child: FlowyHover( config: HoverDisplayConfig(hoverColor: theme.bg3), diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart new file mode 100644 index 0000000000..8d2e948b68 --- /dev/null +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -0,0 +1,33 @@ +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; +import 'package:app_flowy/workspace/presentation/stack_page/trash_page.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +class MenuTrash extends StatelessWidget { + const MenuTrash({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 26, + child: InkWell( + onTap: () { + getIt().setStack(TrashStackContext()); + }, + child: _render(context), + ), + ); + } + + Widget _render(BuildContext context) { + return Row(children: [ + SizedBox(width: 16, height: 16, child: svg("home/trash")), + const HSpace(6), + const FlowyText.medium('Trash', fontSize: 12), + ]); + } +} diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart index ceb93e4654..f24d38d9c9 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart @@ -11,6 +11,8 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart'; class MenuUser extends MenuItem { final UserProfile user; MenuUser(this.user, {Key? key}) : super(key: ValueKey(user.id)); + @override + MenuItemType get type => MenuItemType.userProfile; @override Widget build(BuildContext context) { @@ -60,7 +62,4 @@ class MenuUser extends MenuItem { }, ); } - - @override - MenuItemType get type => MenuItemType.userProfile; }