diff --git a/app_flowy/lib/startup/tasks/application_task.dart b/app_flowy/lib/startup/tasks/application_task.dart index b099878f0c..07875d83bd 100644 --- a/app_flowy/lib/startup/tasks/application_task.dart +++ b/app_flowy/lib/startup/tasks/application_task.dart @@ -31,9 +31,9 @@ class ApplicationWidget extends StatelessWidget { Widget build(BuildContext context) { const ratio = 1.73; const minWidth = 500.0; - const launchWidth = 1310.0; setWindowMinSize(const Size(minWidth, minWidth / ratio)); - setWindowFrame(const Rect.fromLTRB(0, 0, launchWidth, launchWidth / ratio)); + // const launchWidth = 1310.0; + // setWindowFrame(const Rect.fromLTWH(0, 0, launchWidth, launchWidth / ratio)); final theme = AppTheme.fromType(ThemeType.light); FlowyOverlayConfig config = FlowyOverlayConfig(barrierColor: Colors.transparent); diff --git a/app_flowy/lib/workspace/application/app/app_bloc.dart b/app_flowy/lib/workspace/application/app/app_bloc.dart index d5978484b4..7faa22a7cc 100644 --- a/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -21,8 +21,7 @@ class AppBloc extends Bloc<AppEvent, AppState> { yield* _fetchViews(); }, createView: (CreateView value) async* { - final viewOrFailed = await iAppImpl.createView( - name: value.name, desc: value.desc, viewType: value.viewType); + final viewOrFailed = await iAppImpl.createView(name: value.name, desc: value.desc, viewType: value.viewType); yield viewOrFailed.fold((view) => state, (error) { Log.error(error); return state.copyWith(successOrFailure: right(error)); @@ -46,8 +45,7 @@ class AppBloc extends Bloc<AppEvent, AppState> { @freezed class AppEvent with _$AppEvent { const factory AppEvent.initial() = Initial; - const factory AppEvent.createView( - String name, String desc, ViewType viewType) = CreateView; + const factory AppEvent.createView(String name, String desc, ViewType viewType) = CreateView; } @freezed diff --git a/app_flowy/lib/workspace/application/app/app_listen_bloc.dart b/app_flowy/lib/workspace/application/app/app_listen_bloc.dart index 3a44b1c92f..820c846345 100644 --- a/app_flowy/lib/workspace/application/app/app_listen_bloc.dart +++ b/app_flowy/lib/workspace/application/app/app_listen_bloc.dart @@ -19,9 +19,9 @@ class AppListenBloc extends Bloc<AppListenEvent, AppListenState> { listener.start( addViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail), ); - }, viewsReceived: (ViewsReceived value) async* { + }, didReceiveViews: (ViewsReceived value) async* { yield value.viewsOrFail.fold( - (views) => AppListenState.loadViews(views), + (views) => AppListenState.didReceiveViews(views), (error) => AppListenState.loadFail(error), ); }); @@ -29,8 +29,8 @@ class AppListenBloc extends Bloc<AppListenEvent, AppListenState> { void _handleViewsOrFail(Either<List<View>, WorkspaceError> viewsOrFail) { viewsOrFail.fold( - (views) => add(AppListenEvent.viewsReceived(left(views))), - (error) => add(AppListenEvent.viewsReceived(right(error))), + (views) => add(AppListenEvent.didReceiveViews(left(views))), + (error) => add(AppListenEvent.didReceiveViews(right(error))), ); } } @@ -38,14 +38,14 @@ class AppListenBloc extends Bloc<AppListenEvent, AppListenState> { @freezed class AppListenEvent with _$AppListenEvent { const factory AppListenEvent.started() = _Started; - const factory AppListenEvent.viewsReceived(Either<List<View>, WorkspaceError> viewsOrFail) = ViewsReceived; + const factory AppListenEvent.didReceiveViews(Either<List<View>, WorkspaceError> viewsOrFail) = ViewsReceived; } @freezed class AppListenState with _$AppListenState { const factory AppListenState.initial() = _Initial; - const factory AppListenState.loadViews( + const factory AppListenState.didReceiveViews( List<View> views, ) = _LoadViews; diff --git a/app_flowy/lib/workspace/application/app/app_listen_bloc.freezed.dart b/app_flowy/lib/workspace/application/app/app_listen_bloc.freezed.dart index 6841f641d3..f68ddf4352 100644 --- a/app_flowy/lib/workspace/application/app/app_listen_bloc.freezed.dart +++ b/app_flowy/lib/workspace/application/app/app_listen_bloc.freezed.dart @@ -20,7 +20,8 @@ class _$AppListenEventTearOff { return const _Started(); } - ViewsReceived viewsReceived(Either<List<View>, WorkspaceError> viewsOrFail) { + ViewsReceived didReceiveViews( + Either<List<View>, WorkspaceError> viewsOrFail) { return ViewsReceived( viewsOrFail, ); @@ -36,27 +37,27 @@ mixin _$AppListenEvent { TResult when<TResult extends Object?>({ required TResult Function() started, required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail) - viewsReceived, + didReceiveViews, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>({ TResult Function()? started, TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)? - viewsReceived, + didReceiveViews, required TResult orElse(), }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Started value) started, - required TResult Function(ViewsReceived value) viewsReceived, + required TResult Function(ViewsReceived value) didReceiveViews, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Started value)? started, - TResult Function(ViewsReceived value)? viewsReceived, + TResult Function(ViewsReceived value)? didReceiveViews, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -118,7 +119,7 @@ class _$_Started implements _Started { TResult when<TResult extends Object?>({ required TResult Function() started, required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail) - viewsReceived, + didReceiveViews, }) { return started(); } @@ -128,7 +129,7 @@ class _$_Started implements _Started { TResult maybeWhen<TResult extends Object?>({ TResult Function()? started, TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)? - viewsReceived, + didReceiveViews, required TResult orElse(), }) { if (started != null) { @@ -141,7 +142,7 @@ class _$_Started implements _Started { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Started value) started, - required TResult Function(ViewsReceived value) viewsReceived, + required TResult Function(ViewsReceived value) didReceiveViews, }) { return started(this); } @@ -150,7 +151,7 @@ class _$_Started implements _Started { @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Started value)? started, - TResult Function(ViewsReceived value)? viewsReceived, + TResult Function(ViewsReceived value)? didReceiveViews, required TResult orElse(), }) { if (started != null) { @@ -206,7 +207,7 @@ class _$ViewsReceived implements ViewsReceived { @override String toString() { - return 'AppListenEvent.viewsReceived(viewsOrFail: $viewsOrFail)'; + return 'AppListenEvent.didReceiveViews(viewsOrFail: $viewsOrFail)'; } @override @@ -232,9 +233,9 @@ class _$ViewsReceived implements ViewsReceived { TResult when<TResult extends Object?>({ required TResult Function() started, required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail) - viewsReceived, + didReceiveViews, }) { - return viewsReceived(viewsOrFail); + return didReceiveViews(viewsOrFail); } @override @@ -242,11 +243,11 @@ class _$ViewsReceived implements ViewsReceived { TResult maybeWhen<TResult extends Object?>({ TResult Function()? started, TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)? - viewsReceived, + didReceiveViews, required TResult orElse(), }) { - if (viewsReceived != null) { - return viewsReceived(viewsOrFail); + if (didReceiveViews != null) { + return didReceiveViews(viewsOrFail); } return orElse(); } @@ -255,20 +256,20 @@ class _$ViewsReceived implements ViewsReceived { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Started value) started, - required TResult Function(ViewsReceived value) viewsReceived, + required TResult Function(ViewsReceived value) didReceiveViews, }) { - return viewsReceived(this); + return didReceiveViews(this); } @override @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Started value)? started, - TResult Function(ViewsReceived value)? viewsReceived, + TResult Function(ViewsReceived value)? didReceiveViews, required TResult orElse(), }) { - if (viewsReceived != null) { - return viewsReceived(this); + if (didReceiveViews != null) { + return didReceiveViews(this); } return orElse(); } @@ -293,7 +294,7 @@ class _$AppListenStateTearOff { return const _Initial(); } - _LoadViews loadViews(List<View> views) { + _LoadViews didReceiveViews(List<View> views) { return _LoadViews( views, ); @@ -314,14 +315,14 @@ mixin _$AppListenState { @optionalTypeArgs TResult when<TResult extends Object?>({ required TResult Function() initial, - required TResult Function(List<View> views) loadViews, + required TResult Function(List<View> views) didReceiveViews, required TResult Function(WorkspaceError error) loadFail, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>({ TResult Function()? initial, - TResult Function(List<View> views)? loadViews, + TResult Function(List<View> views)? didReceiveViews, TResult Function(WorkspaceError error)? loadFail, required TResult orElse(), }) => @@ -329,14 +330,14 @@ mixin _$AppListenState { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Initial value) initial, - required TResult Function(_LoadViews value) loadViews, + required TResult Function(_LoadViews value) didReceiveViews, required TResult Function(_LoadFail value) loadFail, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Initial value)? initial, - TResult Function(_LoadViews value)? loadViews, + TResult Function(_LoadViews value)? didReceiveViews, TResult Function(_LoadFail value)? loadFail, required TResult orElse(), }) => @@ -398,7 +399,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult when<TResult extends Object?>({ required TResult Function() initial, - required TResult Function(List<View> views) loadViews, + required TResult Function(List<View> views) didReceiveViews, required TResult Function(WorkspaceError error) loadFail, }) { return initial(); @@ -408,7 +409,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult maybeWhen<TResult extends Object?>({ TResult Function()? initial, - TResult Function(List<View> views)? loadViews, + TResult Function(List<View> views)? didReceiveViews, TResult Function(WorkspaceError error)? loadFail, required TResult orElse(), }) { @@ -422,7 +423,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Initial value) initial, - required TResult Function(_LoadViews value) loadViews, + required TResult Function(_LoadViews value) didReceiveViews, required TResult Function(_LoadFail value) loadFail, }) { return initial(this); @@ -432,7 +433,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Initial value)? initial, - TResult Function(_LoadViews value)? loadViews, + TResult Function(_LoadViews value)? didReceiveViews, TResult Function(_LoadFail value)? loadFail, required TResult orElse(), }) { @@ -487,7 +488,7 @@ class _$_LoadViews implements _LoadViews { @override String toString() { - return 'AppListenState.loadViews(views: $views)'; + return 'AppListenState.didReceiveViews(views: $views)'; } @override @@ -511,22 +512,22 @@ class _$_LoadViews implements _LoadViews { @optionalTypeArgs TResult when<TResult extends Object?>({ required TResult Function() initial, - required TResult Function(List<View> views) loadViews, + required TResult Function(List<View> views) didReceiveViews, required TResult Function(WorkspaceError error) loadFail, }) { - return loadViews(views); + return didReceiveViews(views); } @override @optionalTypeArgs TResult maybeWhen<TResult extends Object?>({ TResult Function()? initial, - TResult Function(List<View> views)? loadViews, + TResult Function(List<View> views)? didReceiveViews, TResult Function(WorkspaceError error)? loadFail, required TResult orElse(), }) { - if (loadViews != null) { - return loadViews(views); + if (didReceiveViews != null) { + return didReceiveViews(views); } return orElse(); } @@ -535,22 +536,22 @@ class _$_LoadViews implements _LoadViews { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Initial value) initial, - required TResult Function(_LoadViews value) loadViews, + required TResult Function(_LoadViews value) didReceiveViews, required TResult Function(_LoadFail value) loadFail, }) { - return loadViews(this); + return didReceiveViews(this); } @override @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Initial value)? initial, - TResult Function(_LoadViews value)? loadViews, + TResult Function(_LoadViews value)? didReceiveViews, TResult Function(_LoadFail value)? loadFail, required TResult orElse(), }) { - if (loadViews != null) { - return loadViews(this); + if (didReceiveViews != null) { + return didReceiveViews(this); } return orElse(); } @@ -628,7 +629,7 @@ class _$_LoadFail implements _LoadFail { @optionalTypeArgs TResult when<TResult extends Object?>({ required TResult Function() initial, - required TResult Function(List<View> views) loadViews, + required TResult Function(List<View> views) didReceiveViews, required TResult Function(WorkspaceError error) loadFail, }) { return loadFail(error); @@ -638,7 +639,7 @@ class _$_LoadFail implements _LoadFail { @optionalTypeArgs TResult maybeWhen<TResult extends Object?>({ TResult Function()? initial, - TResult Function(List<View> views)? loadViews, + TResult Function(List<View> views)? didReceiveViews, TResult Function(WorkspaceError error)? loadFail, required TResult orElse(), }) { @@ -652,7 +653,7 @@ class _$_LoadFail implements _LoadFail { @optionalTypeArgs TResult map<TResult extends Object?>({ required TResult Function(_Initial value) initial, - required TResult Function(_LoadViews value) loadViews, + required TResult Function(_LoadViews value) didReceiveViews, required TResult Function(_LoadFail value) loadFail, }) { return loadFail(this); @@ -662,7 +663,7 @@ class _$_LoadFail implements _LoadFail { @optionalTypeArgs TResult maybeMap<TResult extends Object?>({ TResult Function(_Initial value)? initial, - TResult Function(_LoadViews value)? loadViews, + TResult Function(_LoadViews value)? didReceiveViews, TResult Function(_LoadFail value)? loadFail, required TResult orElse(), }) { diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart index c4c7203bc6..84ccbacc09 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart @@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/header. import 'package:expandable/expandable.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; @@ -22,13 +21,40 @@ class MenuAppSizes { class MenuAppContext { final App app; - final viewListData = ViewSectionData(); + final viewList = ViewListNotifier(); MenuAppContext(this.app); Key valueKey() => ValueKey("${app.id}${app.version}"); } +// [[diagram: MenuApp]] +// ┌────────┐ +// ┌────▶│AppBloc │────────────────┐ +// │ └────────┘ │ +// │ │ +// │ 1.1 fetch views │ +// │ 1.2 update the MenuAppContext │ +// │ with the views │ +// │ ▼ 3.render sections +// ┌────────┐ │ ┌──────────────┐ ┌──────────────┐ +// │MenuApp │────┤ │MenuAppContext│─┬──▶│ ViewSection │────────────────┐ +// └────────┘ │ └──────────────┘ │ └──────────────┘ │ +// │ ▲ │ │ +// │ │ │ │ +// │ │ hold │ │ +// │ │ │ bind ▼ +// │ │ │ ┌─────────────────┐ ┌────────────────────┐ +// │ ┌──────────────┐ │ └─▶│ViewListNotifier │──▶│ViewSectionNotifier │ +// └───▶│AppListenBloc │───────────┘ └─────────────────┘ └────────────────────┘ +// └──────────────┘ +// 4.notifier binding. So The ViewSection +// 2.1 listen on the app will be re rebuild if the the number of +// 2.2 notify if the number of the app's view the views in MenuAppContext was changed. +// was changed +// 2.3 update MenuAppContext with the new +// views + class MenuApp extends MenuItem { final MenuAppContext appCtx; MenuApp(this.appCtx, {Key? key}) : super(key: appCtx.valueKey()); @@ -43,23 +69,35 @@ class MenuApp extends MenuItem { return appBloc; }), BlocProvider<AppListenBloc>(create: (context) { - final watchBloc = getIt<AppListenBloc>(param1: appCtx.app.id); - watchBloc.add(const AppListenEvent.started()); - return watchBloc; + final listener = getIt<AppListenBloc>(param1: appCtx.app.id); + listener.add(const AppListenEvent.started()); + return listener; }), ], - child: BlocBuilder<AppListenBloc, AppListenState>( - builder: (context, state) { - final child = state.map( - initial: (_) => BlocBuilder<AppBloc, AppState>( - builder: (context, state) => _renderViewSection(state.views), + child: MultiBlocListener( + listeners: [ + BlocListener<AppListenBloc, AppListenState>( + listenWhen: (p, c) => p != c, + listener: (context, state) => state.map( + initial: (_) => {}, + didReceiveViews: (state) => appCtx.viewList.items = state.views, + loadFail: (s) => appCtx.viewList.items = [], ), - loadViews: (s) => _renderViewSection(s.views), - loadFail: (s) => FlowyErrorPage(s.error.toString()), - ); - - return expandableWrapper(context, child); - }, + ), + ], + child: BlocBuilder<AppListenBloc, AppListenState>( + builder: (context, state) { + final child = state.map( + initial: (_) => BlocBuilder<AppBloc, AppState>(builder: (context, state) { + appCtx.viewList.items = state.views ?? List.empty(growable: false); + return _renderViewSection(appCtx.viewList); + }), + didReceiveViews: (state) => _renderViewSection(appCtx.viewList), + loadFail: (s) => FlowyErrorPage(s.error.toString()), + ); + return expandableWrapper(context, child); + }, + ), ), ); } @@ -90,14 +128,13 @@ class MenuApp extends MenuItem { ); } - Widget _renderViewSection(List<View>? views) { - appCtx.viewListData.views = views ?? List.empty(growable: false); + Widget _renderViewSection(ViewListNotifier viewListNotifier) { return MultiProvider( providers: [ - ChangeNotifierProvider.value(value: appCtx.viewListData), + ChangeNotifierProvider.value(value: viewListNotifier), ], - child: Consumer(builder: (context, ViewSectionData notifier, child) { - return ViewSection(notifier.views).padding(vertical: 8); + child: Consumer(builder: (context, ViewListNotifier notifier, child) { + return ViewSection(notifier.items).padding(vertical: 8); }), ); } 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 40ba369b72..c3d769caa8 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 @@ -40,6 +40,8 @@ class ViewSectionItem extends StatefulWidget { State<ViewSectionItem> createState() => _ViewSectionItemState(); } +// [[Widget: LifeCycle]] +// https://flutterbyexample.com/lesson/stateful-widget-lifecycle class _ViewSectionItemState extends State<ViewSectionItem> { bool isOnSelected = false; @@ -75,15 +77,14 @@ class _ViewSectionItemState extends State<ViewSectionItem> { children.add(const Spacer()); children.add(ViewDisclosureButton( onTap: () { - setState(() { - isOnSelected = true; - }); + setState( + () => isOnSelected = true, + ); }, onSelected: (selected) { selected.fold(() => null, (action) { debugPrint('$action.name'); }); - setState(() { isOnSelected = false; }); diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart index d842442952..2f97fadbef 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart @@ -8,16 +8,16 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'item.dart'; -class ViewSectionData extends ChangeNotifier { - List<View>? innerViews; - ViewSectionData(); +class ViewListNotifier extends ChangeNotifier { + List<View>? views; + ViewListNotifier(); - set views(List<View> views) { - innerViews = views; + set items(List<View> items) { + views = items; notifyListeners(); } - List<View> get views => innerViews ?? []; + List<View> get items => views ?? []; } class ViewSectionNotifier with ChangeNotifier { @@ -35,8 +35,8 @@ class ViewSectionNotifier with ChangeNotifier { View? get selectedView => _selectedView; - void update(ViewSectionData notifier) { - innerViews = notifier.views; + void update(ViewListNotifier notifier) { + innerViews = notifier.items; notifyListeners(); } } @@ -48,12 +48,12 @@ class ViewSection extends StatelessWidget { @override Widget build(BuildContext context) { // The ViewListNotifier will be updated after ViewListData changed passed by parent widget - return ChangeNotifierProxyProvider<ViewSectionData, ViewSectionNotifier>( + return ChangeNotifierProxyProvider<ViewListNotifier, ViewSectionNotifier>( create: (_) => ViewSectionNotifier( - Provider.of<ViewSectionData>( + Provider.of<ViewListNotifier>( context, listen: false, - ).views, + ).items, ), update: (_, notifier, controller) => controller!..update(notifier), child: Consumer(builder: (context, ViewSectionNotifier notifier, child) {