import 'package:app_flowy/workspace/presentation/widgets/menu/menu_new_app.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu_top_bar.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/menu/menu_bloc.dart'; import 'package:app_flowy/workspace/application/menu/menu_watch.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/app/app_widget.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu_user.dart'; import 'menu_list.dart'; class HomeMenu extends StatelessWidget { final Function(HomeStackView?) pageContextChanged; final Function(bool) isCollapseChanged; final UserDetail user; const HomeMenu( {Key? key, required this.pageContextChanged, required this.isCollapseChanged, required this.user}) : super(key: key); @override Widget build(BuildContext context) { return MultiBlocProvider( providers: [ BlocProvider( create: (context) => getIt(param1: user)..add(const MenuEvent.initial())), BlocProvider( create: (context) => getIt(param1: user) ..add(const MenuWatchEvent.started())), ], child: MultiBlocListener( listeners: [ BlocListener( listenWhen: (p, c) => p.stackView != c.stackView, listener: (context, state) => pageContextChanged(state.stackView), ), BlocListener( listenWhen: (p, c) => p.isCollapse != c.isCollapse, listener: (context, state) => isCollapseChanged(state.isCollapse), ) ], child: BlocBuilder( builder: (context, state) => _renderBody(context), ), ), ); } Widget _renderBody(BuildContext context) { // nested cloumn: https://siddharthmolleti.com/flutter-box-constraints-nested-column-s-row-s-3dfacada7361 return Container( color: Theme.of(context).colorScheme.background, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ _renderTopBar(context), _renderMenuList(context), ], ).padding(horizontal: Insets.l), ), _renderNewAppButton(context), ], ), ); } Widget _renderMenuList(BuildContext context) { return BlocBuilder( builder: (context, state) { return state.map( initial: (_) => MenuList( menuItems: menuItemsWithApps(context.read().state.apps), ), loadApps: (s) => MenuList( menuItems: menuItemsWithApps(some(s.apps)), ), loadFail: (s) => FlowyErrorPage(s.error.toString()), ); }, ); } Widget _renderNewAppButton(BuildContext context) { return NewAppButton( press: (appName) => context.read().add(MenuEvent.createApp(appName, desc: "")), ); } Widget _renderTopBar(BuildContext context) { return SizedBox( height: HomeSizes.menuTopBarHeight, child: const MenuTopBar(), ); } List menuItemsWithApps(Option> someApps) { return MenuItemBuilder().withUser(user).withApps(someApps).build(); } } class MenuItemBuilder { List items = []; MenuItemBuilder(); MenuItemBuilder withUser(UserDetail user) { items.add(MenuUser(user)); return this; } MenuItemBuilder withApps(Option> someApps) { List appWidgets = someApps.foldRight( [], (apps, _) => apps.map((app) => AppWidget(app)).toList(), ); items.addAll(appWidgets); return this; } List build() { return items; } }