[flutter]: config menu trash ui

This commit is contained in:
appflowy 2021-10-12 16:58:05 +08:00
parent 50172e3fd4
commit 0d5a16e447
10 changed files with 162 additions and 71 deletions

View File

@ -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<HomeStackType> pages = HomeStackType.values.toList();
abstract class HomeStackContext extends Equatable with NavigationItem {
List<NavigationItem> 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<ViewType> pages = ViewType.values.toList();

View File

@ -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;
}
}
}

View File

@ -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) {};

View File

@ -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<Object?> 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<BlankStackPage> createState() => _AnnouncementPage();
State<BlankStackPage> createState() => _BlankStackPageState();
}
class _AnnouncementPage extends State<BlankStackPage> {
class _BlankStackPageState extends State<BlankStackPage> {
@override
Widget build(BuildContext context) {
return SizedBox.expand(

View File

@ -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<Object?> get props => [_view.id];

View File

@ -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<Object?> 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<NavigationItem> get navigationItems => [this];
}
class TrashStackPage extends StatefulWidget {
const TrashStackPage({Key? key}) : super(key: key);
@override
State<TrashStackPage> createState() => _TrashStackPageState();
}
class _TrashStackPageState extends State<TrashStackPage> {
@override
Widget build(BuildContext context) {
return SizedBox.expand(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(),
),
),
);
}
}

View File

@ -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<MenuBloc>().state.apps),
menuItems: buildMenuItems(context.read<MenuBloc>().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<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
@ -133,31 +141,14 @@ class HomeMenu extends StatelessWidget {
return const MenuTopBar();
}
List<MenuItem> menuItemsWithApps(Option<List<App>> someApps) {
return MenuItemBuilder().withUser(user).withApps(someApps).build();
}
}
class MenuItemBuilder {
List<MenuItem> items = [];
MenuItemBuilder();
MenuItemBuilder withUser(UserProfile user) {
List<MenuItem> buildMenuItems(Option<List<App>> apps) {
List<MenuItem> items = [];
items.add(MenuUser(user));
return this;
}
MenuItemBuilder withApps(Option<List<App>> someApps) {
List<MenuItem> appWidgets = someApps.foldRight(
[],
(apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList(),
);
List<MenuItem> appWidgets =
apps.foldRight([], (apps, _) => apps.map((app) => MenuApp(MenuAppContext(app))).toList());
items.addAll(appWidgets);
return this;
}
List<MenuItem> build() {
return items;
}
}

View File

@ -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<ViewBloc>().state.view);
getIt<HomeStackManager>().setStack(state.view.intoStackContext());
getIt<HomeStackManager>().setStack(state.view.stackContext());
},
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),

View File

@ -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<HomeStackManager>().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),
]);
}
}

View File

@ -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;
}