diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/export_tab.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/export_tab.dart new file mode 100644 index 0000000000..2443bd0819 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/export_tab.dart @@ -0,0 +1,119 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/document/application/document_share_bloc.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart'; +import 'package:appflowy/startup/startup.dart'; +import 'package:appflowy/util/string_extension.dart'; +import 'package:appflowy/workspace/application/export/document_exporter.dart'; +import 'package:appflowy/workspace/presentation/home/toast.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/file_picker/file_picker_service.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class ExportTab extends StatelessWidget { + const ExportTab({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + const VSpace(10), + _ExportButton( + title: LocaleKeys.shareAction_html.tr(), + svg: FlowySvgs.export_html_s, + onTap: () => _exportHTML(context), + ), + const VSpace(10), + _ExportButton( + title: LocaleKeys.shareAction_markdown.tr(), + svg: FlowySvgs.export_markdown_s, + onTap: () => _exportMarkdown(context), + ), + const VSpace(10), + _ExportButton( + title: LocaleKeys.shareAction_clipboard.tr(), + svg: FlowySvgs.duplicate_s, + onTap: () => _exportToClipboard(context), + ), + ], + ); + } + + Future _exportHTML(BuildContext context) async { + final viewName = context.read().state.viewName; + final exportPath = await getIt().saveFile( + dialogTitle: '', + fileName: '${viewName.toFileName()}.html', + ); + if (context.mounted && exportPath != null) { + context.read().add( + DocumentShareEvent.share( + DocumentShareType.html, + exportPath, + ), + ); + } + } + + Future _exportMarkdown(BuildContext context) async { + final viewName = context.read().state.viewName; + final exportPath = await getIt().saveFile( + dialogTitle: '', + fileName: '${viewName.toFileName()}.md', + ); + if (context.mounted && exportPath != null) { + context.read().add( + DocumentShareEvent.share( + DocumentShareType.markdown, + exportPath, + ), + ); + } + } + + Future _exportToClipboard(BuildContext context) async { + final documentExporter = + DocumentExporter(context.read().view); + final result = await documentExporter.export(DocumentExportType.markdown); + result.fold( + (markdown) => getIt() + .setData(ClipboardServiceData(plainText: markdown)), + (error) => showMessageToast(error.msg), + ); + } +} + +class _ExportButton extends StatelessWidget { + const _ExportButton({ + required this.title, + required this.svg, + required this.onTap, + }); + + final String title; + final FlowySvgData svg; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final radius = BorderRadius.circular(10.0); + return FlowyButton( + margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 14), + iconPadding: 12, + decoration: BoxDecoration( + border: Border.all( + color: const Color(0x1E14171B), + ), + borderRadius: radius, + ), + radius: radius, + text: FlowyText(title), + leftIcon: FlowySvg(svg), + onTap: onTap, + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/publish_tab.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/publish_tab.dart index bd4fdec55a..9b43f91316 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/publish_tab.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/publish_tab.dart @@ -100,10 +100,6 @@ class _PublishedWidgetState extends State<_PublishedWidget> { controller: controller, onCopy: (url) { AppFlowyClipboard.setData(text: url); - showSnackBarMessage( - context, - LocaleKeys.document_inlineLink_copyLink.tr(), - ); }, onSubmitted: (url) {}, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_menu.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_menu.dart index 648e53c4dd..fa9670fe18 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_menu.dart @@ -1,5 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/home/tab/_round_underline_tab_indicator.dart'; +import 'package:appflowy/plugins/document/presentation/share/export_tab.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -112,10 +113,11 @@ class _ShareMenuState extends State switch (selectedTab) { case ShareMenuTab.publish: return const PublishTab(); - + case ShareMenuTab.exportAs: + return const ExportTab(); default: return const Center( - child: FlowyText('coming soon'), + child: FlowyText('🏡 under construction'), ); } } diff --git a/frontend/resources/flowy_icons/16x/export_html.svg b/frontend/resources/flowy_icons/16x/export_html.svg new file mode 100644 index 0000000000..02ae35a2b4 --- /dev/null +++ b/frontend/resources/flowy_icons/16x/export_html.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/resources/flowy_icons/16x/export_markdown.svg b/frontend/resources/flowy_icons/16x/export_markdown.svg new file mode 100644 index 0000000000..a40e5baa26 --- /dev/null +++ b/frontend/resources/flowy_icons/16x/export_markdown.svg @@ -0,0 +1,6 @@ + + + + + +