diff --git a/app_flowy/lib/workspace/application/app/app_bloc.dart b/app_flowy/lib/workspace/application/app/app_bloc.dart index 45200aa8d3..04648820a3 100644 --- a/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -29,7 +29,7 @@ class AppBloc extends Bloc { Stream _fetchViews() async* { final viewsOrFailed = await iAppImpl.getViews(); yield viewsOrFailed.fold( - (apps) => state.copyWith(views: some(apps)), + (apps) => state.copyWith(views: apps), (error) => state.copyWith(successOrFailure: right(error)), ); } @@ -46,13 +46,13 @@ abstract class AppEvent with _$AppEvent { abstract class AppState implements _$AppState { const factory AppState({ required bool isLoading, - required Option> views, + required List? views, required Either successOrFailure, }) = _AppState; factory AppState.initial() => AppState( isLoading: false, - views: none(), + views: null, successOrFailure: left(unit), ); } diff --git a/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart b/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart index e3ca167c2c..44fe44b3fc 100644 --- a/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart +++ b/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart @@ -308,7 +308,7 @@ class _$AppStateTearOff { _AppState call( {required bool isLoading, - required Option> views, + required List? views, required Either successOrFailure}) { return _AppState( isLoading: isLoading, @@ -324,7 +324,7 @@ const $AppState = _$AppStateTearOff(); /// @nodoc mixin _$AppState { bool get isLoading => throw _privateConstructorUsedError; - Option> get views => throw _privateConstructorUsedError; + List? get views => throw _privateConstructorUsedError; Either get successOrFailure => throw _privateConstructorUsedError; @@ -339,7 +339,7 @@ abstract class $AppStateCopyWith<$Res> { _$AppStateCopyWithImpl<$Res>; $Res call( {bool isLoading, - Option> views, + List? views, Either successOrFailure}); } @@ -365,7 +365,7 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> { views: views == freezed ? _value.views : views // ignore: cast_nullable_to_non_nullable - as Option>, + as List?, successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable @@ -381,7 +381,7 @@ abstract class _$AppStateCopyWith<$Res> implements $AppStateCopyWith<$Res> { @override $Res call( {bool isLoading, - Option> views, + List? views, Either successOrFailure}); } @@ -408,7 +408,7 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res> views: views == freezed ? _value.views : views // ignore: cast_nullable_to_non_nullable - as Option>, + as List?, successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable @@ -428,7 +428,7 @@ class _$_AppState implements _AppState { @override final bool isLoading; @override - final Option> views; + final List? views; @override final Either successOrFailure; @@ -467,13 +467,13 @@ class _$_AppState implements _AppState { abstract class _AppState implements AppState { const factory _AppState( {required bool isLoading, - required Option> views, + required List? views, required Either successOrFailure}) = _$_AppState; @override bool get isLoading => throw _privateConstructorUsedError; @override - Option> get views => throw _privateConstructorUsedError; + List? get views => throw _privateConstructorUsedError; @override Either get successOrFailure => throw _privateConstructorUsedError; diff --git a/app_flowy/lib/workspace/presentation/app/app_header.dart b/app_flowy/lib/workspace/presentation/app/app_header.dart new file mode 100644 index 0000000000..d58c50ce4f --- /dev/null +++ b/app_flowy/lib/workspace/presentation/app/app_header.dart @@ -0,0 +1,85 @@ +import 'package:app_flowy/workspace/application/app/app_bloc.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flowy_infra_ui/style_widget/text_button.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 'app_page.dart'; + +class AppHeader extends StatelessWidget { + final App app; + const AppHeader( + this.app, { + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + InkWell( + onTap: () { + ExpandableController.of(context, + rebuildOnChange: false, required: true) + ?.toggle(); + }, + child: ExpandableIcon( + theme: ExpandableThemeData( + expandIcon: Icons.arrow_drop_up, + collapseIcon: Icons.arrow_drop_down, + iconColor: Colors.black, + iconSize: AppPageSize.expandedIconSize, + iconPadding: EdgeInsets.zero, + hasIcon: false, + ), + ), + ), + HSpace(AppPageSize.expandedIconRightSpace), + Expanded( + child: FlowyTextButton( + app.name, + onPressed: () { + debugPrint('show app document'); + }, + ), + ), + // FlowyIconButton( + // icon: const Icon(Icons.add), + // onPressed: () { + // debugPrint('add view'); + // }, + // ), + PopupMenuButton( + iconSize: 20, + tooltip: 'create new view', + icon: const Icon(Icons.add), + padding: EdgeInsets.zero, + onSelected: (viewType) => + _createView(viewType as ViewType, context), + itemBuilder: (context) => menuItemBuilder()) + ], + ); + } + + List menuItemBuilder() { + return ViewType.values + .where((element) => element != ViewType.Blank) + .map((ty) { + return PopupMenuItem( + value: ty, + child: Row( + children: [Text(ty.name)], + )); + }).toList(); + } + + void _createView(ViewType viewType, BuildContext context) { + context.read().add(AppEvent.createView("New view", "", viewType)); + } +} diff --git a/app_flowy/lib/workspace/presentation/app/app_widget.dart b/app_flowy/lib/workspace/presentation/app/app_page.dart similarity index 81% rename from app_flowy/lib/workspace/presentation/app/app_widget.dart rename to app_flowy/lib/workspace/presentation/app/app_page.dart index 9d29712e9c..b932701ee9 100644 --- a/app_flowy/lib/workspace/presentation/app/app_widget.dart +++ b/app_flowy/lib/workspace/presentation/app/app_page.dart @@ -1,4 +1,3 @@ -import 'package:dartz/dartz.dart'; 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'; @@ -9,12 +8,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/app/app_bloc.dart'; import 'package:app_flowy/workspace/application/app/app_watch_bloc.dart'; -import 'package:app_flowy/workspace/presentation/app/view_list.dart'; +import 'package:app_flowy/workspace/presentation/app/view_list_page.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart'; import 'package:provider/provider.dart'; +import 'package:styled_widget/styled_widget.dart'; import 'app_header.dart'; -class AppWidgetSize { +class AppPageSize { static double expandedIconSize = 24; static double expandedIconRightSpace = 8; static double scale = 1; @@ -34,20 +34,20 @@ class ViewListData extends ChangeNotifier { List get views => innerViews ?? []; } -class AppWidgetContext { +class AppPageContext { final App app; final viewListData = ViewListData(); - AppWidgetContext( + AppPageContext( this.app, ); Key valueKey() => ValueKey("${app.id}${app.version}"); } -class AppWidget extends MenuItem { - final AppWidgetContext appCtx; - AppWidget(this.appCtx, {Key? key}) : super(key: appCtx.valueKey()); +class AppPage extends MenuItem { + final AppPageContext appCtx; + AppPage(this.appCtx, {Key? key}) : super(key: appCtx.valueKey()); @override Widget build(BuildContext context) { @@ -70,7 +70,7 @@ class AppWidget extends MenuItem { initial: (_) => BlocBuilder( builder: (context, state) => _renderViewList(state.views), ), - loadViews: (s) => _renderViewList(some(s.views)), + loadViews: (s) => _renderViewList(s.views), loadFail: (s) => FlowyErrorPage(s.error.toString()), ); @@ -106,24 +106,14 @@ class AppWidget extends MenuItem { ); } - Widget _renderViewList(Option> some) { - some.fold( - () { - appCtx.viewListData.views = List.empty(growable: true); - }, - (views) { - appCtx.viewListData.views = views; - }, - ); - + Widget _renderViewList(List? views) { + appCtx.viewListData.views = views ?? List.empty(growable: false); return MultiProvider( providers: [ ChangeNotifierProvider.value(value: appCtx.viewListData), ], child: Consumer(builder: (context, ViewListData notifier, child) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: ViewList(notifier.views)); + return ViewListPage(notifier.views).padding(vertical: 8); }), ); } diff --git a/app_flowy/lib/workspace/presentation/app/view_list.dart b/app_flowy/lib/workspace/presentation/app/view_list_page.dart similarity index 81% rename from app_flowy/lib/workspace/presentation/app/view_list.dart rename to app_flowy/lib/workspace/presentation/app/view_list_page.dart index 7dd61bc579..adf1d9deb2 100644 --- a/app_flowy/lib/workspace/presentation/app/view_list.dart +++ b/app_flowy/lib/workspace/presentation/app/view_list_page.dart @@ -1,4 +1,4 @@ -import 'package:app_flowy/workspace/presentation/app/app_widget.dart'; +import 'package:app_flowy/workspace/presentation/app/app_page.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -6,7 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/view/view_widget.dart'; +import 'package:app_flowy/workspace/presentation/view/view_page.dart'; class ViewListNotifier with ChangeNotifier { List innerViews; @@ -16,7 +16,7 @@ class ViewListNotifier with ChangeNotifier { set views(List views) => innerViews = views; List get views => innerViews; - void openView(View view) { + void setSelectedView(View view) { _selectedView = view; notifyListeners(); } @@ -29,9 +29,9 @@ class ViewListNotifier with ChangeNotifier { } } -class ViewList extends StatelessWidget { +class ViewListPage extends StatelessWidget { final List views; - const ViewList(this.views, {Key? key}) : super(key: key); + const ViewListPage(this.views, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -51,13 +51,13 @@ class ViewList extends StatelessWidget { Widget _renderViews(BuildContext context, List views) { var viewWidgets = views.map((view) { - final viewCtx = ViewWidgetContext(view, - isSelected: _isViewSelected(context, view.id)); + final viewCtx = ViewWidgetContext(view); - final viewWidget = ViewWidget( + final viewWidget = ViewPage( viewCtx: viewCtx, + isSelected: _isViewSelected(context, view.id), onOpen: (view) { - context.read().openView(view); + context.read().setSelectedView(view); final stackView = stackViewFromView(viewCtx.view); getIt().setStackView(stackView); }, diff --git a/app_flowy/lib/workspace/presentation/doc/doc_page.dart b/app_flowy/lib/workspace/presentation/doc/doc_page.dart index 08c3148a05..6bb4e3cad2 100644 --- a/app_flowy/lib/workspace/presentation/doc/doc_page.dart +++ b/app_flowy/lib/workspace/presentation/doc/doc_page.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/view/doc_watch_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; -import 'package:app_flowy/workspace/presentation/doc/editor_widget.dart'; +import 'package:app_flowy/workspace/presentation/doc/editor_page.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; @@ -31,7 +31,7 @@ class _DocPageState extends State { assert(widget.stackView is DocPageStackView); return state.map( loading: (_) => const FlowyProgressIndicator(), - loadDoc: (s) => EditorWdiget(doc: s.doc), + loadDoc: (s) => EditorPage(doc: s.doc), loadFail: (s) => FlowyErrorPage(s.error.toString()), ); }), diff --git a/app_flowy/lib/workspace/presentation/doc/editor_widget.dart b/app_flowy/lib/workspace/presentation/doc/editor_page.dart similarity index 94% rename from app_flowy/lib/workspace/presentation/doc/editor_widget.dart rename to app_flowy/lib/workspace/presentation/doc/editor_page.dart index 9a4e41c9b6..9f32229823 100644 --- a/app_flowy/lib/workspace/presentation/doc/editor_widget.dart +++ b/app_flowy/lib/workspace/presentation/doc/editor_page.dart @@ -7,12 +7,12 @@ import 'package:flowy_editor/flowy_editor.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class EditorWdiget extends StatelessWidget { +class EditorPage extends StatelessWidget { final FocusNode _focusNode = FocusNode(); late EditorController controller; final Doc doc; - EditorWdiget({Key? key, required this.doc}) : super(key: key) { + EditorPage({Key? key, required this.doc}) : super(key: key) { controller = EditorController( document: doc.data, selection: const TextSelection.collapsed(offset: 0), diff --git a/app_flowy/lib/workspace/presentation/view/view_widget.dart b/app_flowy/lib/workspace/presentation/view/view_page.dart similarity index 85% rename from app_flowy/lib/workspace/presentation/view/view_widget.dart rename to app_flowy/lib/workspace/presentation/view/view_page.dart index 63a89ea6e6..1b787ce49d 100644 --- a/app_flowy/lib/workspace/presentation/view/view_widget.dart +++ b/app_flowy/lib/workspace/presentation/view/view_page.dart @@ -4,27 +4,28 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/workspace/domain/image.dart'; -import 'package:app_flowy/workspace/presentation/app/app_widget.dart'; +import 'package:app_flowy/workspace/presentation/app/app_page.dart'; import 'package:styled_widget/styled_widget.dart'; class ViewWidgetContext { final View view; - bool isSelected; - ViewWidgetContext( - this.view, { - this.isSelected = false, - }); + ViewWidgetContext(this.view); Key valueKey() => ValueKey("${view.id}${view.version}"); } typedef OpenViewCallback = void Function(View); -class ViewWidget extends StatelessWidget { +class ViewPage extends StatelessWidget { final ViewWidgetContext viewCtx; + final bool isSelected; final OpenViewCallback onOpen; - ViewWidget({Key? key, required this.viewCtx, required this.onOpen}) + ViewPage( + {Key? key, + required this.viewCtx, + required this.onOpen, + required this.isSelected}) : super(key: viewCtx.valueKey()); @override @@ -62,11 +63,11 @@ class ViewWidget extends StatelessWidget { Widget widget = Row(children: children).padding( vertical: 5, - left: AppWidgetSize.expandedPadding, + left: AppPageSize.expandedPadding, right: 5, ); - if (viewCtx.isSelected) { + if (isSelected) { widget = FlowyHoverBackground(child: widget, config: config); } diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/app_flowy/lib/workspace/presentation/widgets/menu/menu_page.dart similarity index 96% rename from app_flowy/lib/workspace/presentation/widgets/menu/menu.dart rename to app_flowy/lib/workspace/presentation/widgets/menu/menu_page.dart index 6052f483df..2a58612c74 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/menu_page.dart @@ -13,7 +13,7 @@ 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/app/app_page.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu_user.dart'; @@ -130,7 +130,7 @@ class MenuItemBuilder { MenuItemBuilder withApps(Option> someApps) { List appWidgets = someApps.foldRight( [], - (apps, _) => apps.map((app) => AppWidget(AppWidgetContext(app))).toList(), + (apps, _) => apps.map((app) => AppPage(AppPageContext(app))).toList(), ); items.addAll(appWidgets); return this; diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart b/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart index c08dc66133..939e344bb1 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/prelude.dart @@ -1 +1 @@ -export 'menu.dart'; +export 'menu_page.dart'; diff --git a/app_flowy/lib/workspace/presentation/widgets/prelude.dart b/app_flowy/lib/workspace/presentation/widgets/prelude.dart index 8a9f575646..c6106aa1c8 100644 --- a/app_flowy/lib/workspace/presentation/widgets/prelude.dart +++ b/app_flowy/lib/workspace/presentation/widgets/prelude.dart @@ -2,4 +2,4 @@ export './blank_page.dart'; export './edit_pannel/edit_pannel.dart'; export './edit_pannel/pannel_animation.dart'; export './home_top_bar.dart'; -export 'menu/menu.dart'; +export 'menu/menu_page.dart';