From b1668bfe6caee01897d83c624689d23c745a7652 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 9 Nov 2021 23:13:04 +0800 Subject: [PATCH] [flutter]: customize home topbar action widget --- .../application/menu/menu_bloc.freezed.dart | 64 +++++---- .../domain/page_stack/page_stack.dart | 4 +- .../stack_page/blank/blank_page.dart | 3 + .../stack_page/doc/doc_stack_page.dart | 126 +++++++++++++++++- .../stack_page/trash/trash_page.dart | 4 + .../widgets/float_bubble/question_bubble.dart | 38 +++--- .../presentation/widgets/home_top_bar.dart | 28 ++-- .../menu/widget/app/header/header.dart | 3 +- .../widget/app/header/right_click_action.dart | 14 +- .../widget/app/section/disclosure_action.dart | 2 +- .../presentation/widgets/pop_up_action.dart | 10 +- .../src/handlers/view_handler.rs | 8 +- .../src/services/view_controller.rs | 12 +- 13 files changed, 222 insertions(+), 94 deletions(-) diff --git a/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart b/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart index 3ca0606f63..8d1ae22278 100644 --- a/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart +++ b/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart @@ -24,7 +24,7 @@ class _$MenuEventTearOff { return const Collapse(); } - OpenPage openPage(HomeStackContext context) { + OpenPage openPage(HomeStackContext context) { return OpenPage( context, ); @@ -53,7 +53,8 @@ mixin _$MenuEvent { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -63,7 +64,7 @@ mixin _$MenuEvent { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -145,7 +146,8 @@ class _$_Initial implements _Initial { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -158,7 +160,7 @@ class _$_Initial implements _Initial { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -242,7 +244,8 @@ class _$Collapse implements Collapse { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -255,7 +258,7 @@ class _$Collapse implements Collapse { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -304,7 +307,7 @@ abstract class Collapse implements MenuEvent { abstract class $OpenPageCopyWith<$Res> { factory $OpenPageCopyWith(OpenPage value, $Res Function(OpenPage) then) = _$OpenPageCopyWithImpl<$Res>; - $Res call({HomeStackContext context}); + $Res call({HomeStackContext context}); } /// @nodoc @@ -324,7 +327,7 @@ class _$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res> context == freezed ? _value.context : context // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + as HomeStackContext, )); } } @@ -335,7 +338,7 @@ class _$OpenPage implements OpenPage { const _$OpenPage(this.context); @override - final HomeStackContext context; + final HomeStackContext context; @override String toString() { @@ -364,7 +367,8 @@ class _$OpenPage implements OpenPage { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -377,7 +381,7 @@ class _$OpenPage implements OpenPage { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -419,9 +423,11 @@ class _$OpenPage implements OpenPage { } abstract class OpenPage implements MenuEvent { - const factory OpenPage(HomeStackContext context) = _$OpenPage; + const factory OpenPage(HomeStackContext context) = + _$OpenPage; - HomeStackContext get context => throw _privateConstructorUsedError; + HomeStackContext get context => + throw _privateConstructorUsedError; @JsonKey(ignore: true) $OpenPageCopyWith get copyWith => throw _privateConstructorUsedError; @@ -502,7 +508,8 @@ class _$CreateApp implements CreateApp { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -515,7 +522,7 @@ class _$CreateApp implements CreateApp { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -633,7 +640,8 @@ class _$ReceiveApps implements ReceiveApps { TResult when({ required TResult Function() initial, required TResult Function() collapse, - required TResult Function(HomeStackContext context) openPage, + required TResult Function(HomeStackContext context) + openPage, required TResult Function(String name, String? desc) createApp, required TResult Function(Either, WorkspaceError> appsOrFail) didReceiveApps, @@ -646,7 +654,7 @@ class _$ReceiveApps implements ReceiveApps { TResult maybeWhen({ TResult Function()? initial, TResult Function()? collapse, - TResult Function(HomeStackContext context)? openPage, + TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, TResult Function(Either, WorkspaceError> appsOrFail)? didReceiveApps, @@ -706,7 +714,7 @@ class _$MenuStateTearOff { {required bool isCollapse, required Option> apps, required Either successOrFailure, - required HomeStackContext context}) { + required HomeStackContext context}) { return _MenuState( isCollapse: isCollapse, apps: apps, @@ -725,7 +733,8 @@ mixin _$MenuState { Option> get apps => throw _privateConstructorUsedError; Either get successOrFailure => throw _privateConstructorUsedError; - HomeStackContext get context => throw _privateConstructorUsedError; + HomeStackContext get context => + throw _privateConstructorUsedError; @JsonKey(ignore: true) $MenuStateCopyWith get copyWith => @@ -740,7 +749,7 @@ abstract class $MenuStateCopyWith<$Res> { {bool isCollapse, Option> apps, Either successOrFailure, - HomeStackContext context}); + HomeStackContext context}); } /// @nodoc @@ -774,7 +783,7 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> { context: context == freezed ? _value.context : context // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + as HomeStackContext, )); } } @@ -789,7 +798,7 @@ abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> { {bool isCollapse, Option> apps, Either successOrFailure, - HomeStackContext context}); + HomeStackContext context}); } /// @nodoc @@ -824,7 +833,7 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res> context: context == freezed ? _value.context : context // ignore: cast_nullable_to_non_nullable - as HomeStackContext, + as HomeStackContext, )); } } @@ -845,7 +854,7 @@ class _$_MenuState implements _MenuState { @override final Either successOrFailure; @override - final HomeStackContext context; + final HomeStackContext context; @override String toString() { @@ -887,7 +896,7 @@ abstract class _MenuState implements MenuState { {required bool isCollapse, required Option> apps, required Either successOrFailure, - required HomeStackContext context}) = _$_MenuState; + required HomeStackContext context}) = _$_MenuState; @override bool get isCollapse => throw _privateConstructorUsedError; @@ -897,7 +906,8 @@ abstract class _MenuState implements MenuState { Either get successOrFailure => throw _privateConstructorUsedError; @override - HomeStackContext get context => throw _privateConstructorUsedError; + HomeStackContext get context => + throw _privateConstructorUsedError; @override @JsonKey(ignore: true) _$MenuStateCopyWith<_MenuState> get copyWith => 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 4731c4c6d2..5654f0eb0c 100644 --- a/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -25,12 +25,14 @@ enum HomeStackType { List pages = HomeStackType.values.toList(); -abstract class HomeStackContext with NavigationItem { +abstract class HomeStackContext with NavigationItem { List get navigationItems; @override Widget get naviTitle; + Widget? Function(BuildContext context) get buildNavigationActions; + @override String get identifier; 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 55bb2f4735..cf57917db5 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 @@ -11,6 +11,9 @@ class BlankStackContext extends HomeStackContext { @override Widget get naviTitle => const FlowyText.medium('Blank page', fontSize: 12); + @override + Widget? Function(BuildContext context) get buildNavigationActions => (_) => null; + @override HomeStackType get type => HomeStackType.blank; 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 9e19a027aa..fa65236450 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 @@ -2,13 +2,18 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/domain/view_ext.dart'; +import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; +import 'package:dartz/dartz.dart' as dartz; import 'doc_page.dart'; -class DocStackContext extends HomeStackContext { +class DocStackContext extends HomeStackContext { View _view; late IViewListener _listener; final ValueNotifier _isUpdated = ValueNotifier(""); @@ -29,15 +34,18 @@ class DocStackContext extends HomeStackContext { @override Widget get naviTitle => FlowyText.medium(_view.name, fontSize: 12); + + @override + Widget? Function(BuildContext context) get buildNaviAction => _buildNaviAction; + @override String get identifier => _view.id; + @override HomeStackType get type => _view.stackType(); @override - Widget buildWidget() { - return DocStackPage(_view, key: ValueKey(_view.id)); - } + Widget buildWidget() => DocStackPage(_view, key: ValueKey(_view.id)); @override List get navigationItems => _makeNavigationItems(); @@ -50,15 +58,52 @@ class DocStackContext extends HomeStackContext { // }).toList(); List _makeNavigationItems() { - return [ - this, - ]; + return [this]; } @override void dispose() { _listener.stop(); } + + Widget _buildNaviAction(BuildContext context) { + return const DocShareButton(); + } +} + +class DocShareButton extends StatelessWidget { + const DocShareButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + double buttonWidth = 60; + return RoundedTextButton( + title: 'Share', + height: 30, + width: buttonWidth, + fontSize: 12, + borderRadius: Corners.s6Border, + color: Colors.lightBlue, + onPressed: () { + final actionList = ShareActions(onSelected: (result) { + result.fold(() {}, (action) { + switch (action) { + case ShareAction.markdown: + break; + case ShareAction.copyLink: + break; + } + }); + }); + actionList.show( + context, + context, + anchorDirection: AnchorDirection.bottomWithCenterAligned, + anchorOffset: Offset(-(buttonWidth / 2), 10), + ); + }, + ); + } } class DocStackPage extends StatefulWidget { @@ -90,3 +135,70 @@ class _DocStackPageState extends State { super.didUpdateWidget(oldWidget); } } + +class ShareActions with ActionList implements FlowyOverlayDelegate { + final Function(dartz.Option) onSelected; + final _items = ShareAction.values.map((action) => ShareActionWrapper(action)).toList(); + + ShareActions({ + required this.onSelected, + }); + + @override + double get maxWidth => 130; + + @override + double get itemHeight => 22; + + @override + List get items => _items; + + @override + void Function(dartz.Option p1) get selectCallback => (result) { + result.fold( + () => onSelected(dartz.none()), + (wrapper) => onSelected( + dartz.some(wrapper.inner), + ), + ); + }; + + @override + FlowyOverlayDelegate? get delegate => this; + + @override + void didRemove() { + onSelected(dartz.none()); + } + + @override + ListOverlayFooter? get footer => null; +} + +enum ShareAction { + markdown, + copyLink, +} + +class ShareActionWrapper extends ActionItem { + final ShareAction inner; + + ShareActionWrapper(this.inner); + + @override + Widget? get icon => null; + + @override + String get name => inner.name; +} + +extension QuestionBubbleExtension on ShareAction { + String get name { + switch (this) { + case ShareAction.markdown: + return "Markdown"; + case ShareAction.copyLink: + return "Copy Link"; + } + } +} diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index 084025c574..53398869b3 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/trash/trash_bloc.dart'; import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/sizes.dart'; import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/trash_cell.dart'; +import 'package:app_flowy/workspace/presentation/widgets/home_top_bar.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; @@ -27,6 +28,9 @@ class TrashStackContext extends HomeStackContext { @override Widget get naviTitle => const FlowyText.medium('Trash', fontSize: 12); + @override + Widget? Function(BuildContext context) get buildNavigationActions => (_) => null; + @override HomeStackType get type => HomeStackType.trash; diff --git a/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart b/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart index 1500d99ccc..5cf241e882 100644 --- a/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart +++ b/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart @@ -22,21 +22,21 @@ class QuestionBubble extends StatelessWidget { height: 30, child: FlowyTextButton( '?', - tooltip: QuestionBubbleAction.values.map((action) => action.name).toList().join(','), + tooltip: BubbleAction.values.map((action) => action.name).toList().join(','), fontSize: 12, fontWeight: FontWeight.w600, fillColor: theme.selector, mainAxisAlignment: MainAxisAlignment.center, radius: BorderRadius.circular(10), onPressed: () { - final actionList = QuestionBubbleActions(onSelected: (result) { + final actionList = QuestionBubbleActionSheet(onSelected: (result) { result.fold(() {}, (action) { switch (action) { - case QuestionBubbleAction.whatsNews: + case BubbleAction.whatsNews: // TODO: annie replace the URL with real ones _launchURL("https://www.appflowy.io/whatsnew"); break; - case QuestionBubbleAction.help: + case BubbleAction.help: // TODO: annie replace the URL with real ones _launchURL("https://discord.gg/9Q2xaN37tV"); break; @@ -63,11 +63,11 @@ class QuestionBubble extends StatelessWidget { } } -class QuestionBubbleActions with ActionList implements FlowyOverlayDelegate { - final Function(dartz.Option) onSelected; - final _items = QuestionBubbleAction.values.map((action) => QuestionBubbleActionWrapper(action)).toList(); +class QuestionBubbleActionSheet with ActionList implements FlowyOverlayDelegate { + final Function(dartz.Option) onSelected; + final _items = BubbleAction.values.map((action) => BubbleActionWrapper(action)).toList(); - QuestionBubbleActions({ + QuestionBubbleActionSheet({ required this.onSelected, }); @@ -78,10 +78,10 @@ class QuestionBubbleActions with ActionList impleme double get itemHeight => 22; @override - List get items => _items; + List get items => _items; @override - void Function(dartz.Option p1) get selectCallback => (result) { + void Function(dartz.Option p1) get selectCallback => (result) { result.fold( () => onSelected(dartz.none()), (wrapper) => onSelected( @@ -145,15 +145,15 @@ class FlowyVersionDescription extends StatelessWidget { } } -enum QuestionBubbleAction { +enum BubbleAction { whatsNews, help, } -class QuestionBubbleActionWrapper extends ActionItemData { - final QuestionBubbleAction inner; +class BubbleActionWrapper extends ActionItem { + final BubbleAction inner; - QuestionBubbleActionWrapper(this.inner); + BubbleActionWrapper(this.inner); @override Widget? get icon => inner.emoji; @@ -161,21 +161,21 @@ class QuestionBubbleActionWrapper extends ActionItemData { String get name => inner.name; } -extension QuestionBubbleExtension on QuestionBubbleAction { +extension QuestionBubbleExtension on BubbleAction { String get name { switch (this) { - case QuestionBubbleAction.whatsNews: + case BubbleAction.whatsNews: return "What's new?"; - case QuestionBubbleAction.help: + case BubbleAction.help: return "Help & Support"; } } Widget get emoji { switch (this) { - case QuestionBubbleAction.whatsNews: + case BubbleAction.whatsNews: return const Text('⭐️', style: TextStyle(fontSize: 12)); - case QuestionBubbleAction.help: + case BubbleAction.help: return const Text('👥', style: TextStyle(fontSize: 12)); } } diff --git a/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart b/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart index af3593f50f..d31db5de29 100644 --- a/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart +++ b/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart @@ -1,14 +1,14 @@ import 'package:app_flowy/workspace/domain/image.dart'; +import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/home/navigation.dart'; -import 'package:flowy_infra/size.dart'; -import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:provider/provider.dart'; class HomeTopBar extends StatelessWidget { const HomeTopBar({Key? key}) : super(key: key); @@ -22,8 +22,14 @@ class HomeTopBar extends StatelessWidget { children: [ const FlowyNavigation(), const Spacer(), - _renderShareButton(), - // _renderMoreButton(), + ChangeNotifierProvider.value( + value: Provider.of(context, listen: false), + child: Consumer( + builder: (BuildContext context, HomeStackNotifier notifier, Widget? child) { + return notifier.stackContext.buildNavigationActions(context) ?? const SizedBox(); + }, + ), + ) // _renderMoreButton(), ], ) .padding( @@ -32,20 +38,6 @@ class HomeTopBar extends StatelessWidget { .bottomBorder(color: Colors.grey.shade300), ); } - - Widget _renderShareButton() { - return RoundedTextButton( - title: 'Share', - height: 30, - width: 60, - fontSize: 12, - borderRadius: Corners.s6Border, - color: Colors.lightBlue, - onPressed: () { - debugPrint('share page'); - }, - ); - } } class HomeTitle extends StatelessWidget { diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index c97c377d6c..0344706573 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -5,7 +5,6 @@ import 'package:flowy_infra/flowy_icon_data_icons.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -79,7 +78,7 @@ class MenuAppHeader extends StatelessWidget { behavior: HitTestBehavior.opaque, onTap: () => ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle(), onSecondaryTap: () { - final actionList = AppDisclosureActions(onSelected: (action) => _handleAction(context, action)); + final actionList = AppDisclosureActionSheet(onSelected: (action) => _handleAction(context, action)); actionList.show( context, context, diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart index b4abfa61af..c8491ee8da 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/right_click_action.dart @@ -4,19 +4,19 @@ import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; -class AppDisclosureActions with ActionList implements FlowyOverlayDelegate { +class AppDisclosureActionSheet with ActionList implements FlowyOverlayDelegate { final Function(dartz.Option) onSelected; - final _items = AppDisclosureAction.values.map((action) => AppDisclosureActionWrapper(action)).toList(); + final _items = AppDisclosureAction.values.map((action) => DisclosureActionWrapper(action)).toList(); - AppDisclosureActions({ + AppDisclosureActionSheet({ required this.onSelected, }); @override - List get items => _items; + List get items => _items; @override - void Function(dartz.Option p1) get selectCallback => (result) { + void Function(dartz.Option p1) get selectCallback => (result) { result.fold( () => onSelected(dartz.none()), (wrapper) => onSelected( @@ -37,10 +37,10 @@ class AppDisclosureActions with ActionList implement ListOverlayFooter? get footer => null; } -class AppDisclosureActionWrapper extends ActionItemData { +class DisclosureActionWrapper extends ActionItem { final AppDisclosureAction inner; - AppDisclosureActionWrapper(this.inner); + DisclosureActionWrapper(this.inner); @override Widget? get icon => inner.icon; diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart index 106d296c95..bb3b14feda 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/disclosure_action.dart @@ -57,7 +57,7 @@ class ViewDisclosureButton extends StatelessWidget ListOverlayFooter? get footer => null; } -class ViewDisclosureActionWrapper extends ActionItemData { +class ViewDisclosureActionWrapper extends ActionItem { final ViewDisclosureAction inner; ViewDisclosureActionWrapper(this.inner); diff --git a/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart b/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart index 01ded84fcc..9addd9481c 100644 --- a/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart +++ b/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart @@ -8,7 +8,7 @@ import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:dartz/dartz.dart' as dartz; -abstract class ActionList { +abstract class ActionList { List get items; String get identifier => toString(); @@ -31,7 +31,7 @@ abstract class ActionList { }) { final widgets = items .map( - (action) => ActionItem( + (action) => ActionCell( action: action, itemHeight: itemHeight, onSelected: (action) { @@ -58,7 +58,7 @@ abstract class ActionList { } } -abstract class ActionItemData { +abstract class ActionItem { Widget? get icon; String get name; } @@ -69,11 +69,11 @@ class ActionListSizes { static double padding = 6; } -class ActionItem extends StatelessWidget { +class ActionCell extends StatelessWidget { final T action; final Function(T) onSelected; final double itemHeight; - const ActionItem({ + const ActionCell({ Key? key, required this.action, required this.onSelected, diff --git a/rust-lib/flowy-workspace/src/handlers/view_handler.rs b/rust-lib/flowy-workspace/src/handlers/view_handler.rs index d04ed77ee2..6e254c872f 100644 --- a/rust-lib/flowy-workspace/src/handlers/view_handler.rs +++ b/rust-lib/flowy-workspace/src/handlers/view_handler.rs @@ -17,7 +17,7 @@ use crate::{ }; use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit}; use flowy_document::entities::doc::DocDelta; -use flowy_workspace_infra::entities::share::{ExportParams, ExportRequest}; +use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest}; use std::{convert::TryInto, sync::Arc}; pub(crate) async fn create_view_handler( @@ -112,8 +112,8 @@ pub(crate) async fn duplicate_view_handler( pub(crate) async fn export_handler( data: Data, controller: Unit>, -) -> Result<(), WorkspaceError> { +) -> DataResult { let params: ExportParams = data.into_inner().try_into()?; - let _ = controller.export_doc(params.into()).await?; - Ok(()) + let data = controller.export_doc(params.into()).await?; + data_result(data) } diff --git a/rust-lib/flowy-workspace/src/services/view_controller.rs b/rust-lib/flowy-workspace/src/services/view_controller.rs index 433bc086ee..1f0f177e5e 100644 --- a/rust-lib/flowy-workspace/src/services/view_controller.rs +++ b/rust-lib/flowy-workspace/src/services/view_controller.rs @@ -139,9 +139,15 @@ impl ViewController { Ok(()) } - #[tracing::instrument(level = "debug", skip(self), err)] - pub(crate) async fn export_doc(&self, _params: ExportParams) -> Result { - unimplemented!() + #[tracing::instrument(level = "debug", skip(self, params), err)] + pub(crate) async fn export_doc(&self, params: ExportParams) -> Result { + let doc_identifier: DocIdentifier = params.doc_id.into(); + let doc = self + .document + .read_document_data(doc_identifier, self.database.db_pool()?) + .await?; + + Ok(ExportData { data: doc.data }) } // belong_to_id will be the app_id or view_id.