mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: the share markdown feature doesn't work in 0.2.0 (#2756)
* chore: bump version 0.2.0 * fix: the share markdown feature doesn't work in 0.2.0 * test: add integration test for share button
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
export 'doc_bloc.dart';
|
||||
export 'doc_service.dart';
|
||||
export 'share_bloc.dart';
|
||||
export 'share_service.dart';
|
||||
|
@ -1,65 +1,46 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:appflowy/plugins/document/application/share_service.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/divider_node_parser.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/math_equation_node_parser.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/code_block_node_parser.dart';
|
||||
import 'package:appflowy/workspace/application/export/document_exporter.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document2/entities.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart'
|
||||
show Document, documentToMarkdown;
|
||||
part 'share_bloc.freezed.dart';
|
||||
|
||||
class DocShareBloc extends Bloc<DocShareEvent, DocShareState> {
|
||||
ShareService service;
|
||||
ViewPB view;
|
||||
DocShareBloc({required this.view, required this.service})
|
||||
: super(const DocShareState.initial()) {
|
||||
on<DocShareEvent>((event, emit) async {
|
||||
await event.map(
|
||||
shareMarkdown: (ShareMarkdown shareMarkdown) async {
|
||||
await service.exportMarkdown(view).then((result) {
|
||||
result.fold(
|
||||
(value) => emit(
|
||||
DocShareState.finish(
|
||||
left(_saveMarkdown(value, shareMarkdown.path)),
|
||||
),
|
||||
),
|
||||
(error) => emit(DocShareState.finish(right(error))),
|
||||
);
|
||||
});
|
||||
|
||||
emit(const DocShareState.loading());
|
||||
},
|
||||
shareLink: (ShareLink value) {},
|
||||
shareText: (ShareText value) {},
|
||||
);
|
||||
});
|
||||
DocShareBloc({
|
||||
required this.view,
|
||||
}) : super(const DocShareState.initial()) {
|
||||
on<ShareMarkdown>(_onShareMarkdown);
|
||||
}
|
||||
|
||||
ExportDataPB _saveMarkdown(ExportDataPB value, String path) {
|
||||
final markdown = _convertDocumentToMarkdown(value);
|
||||
value.data = markdown;
|
||||
File(path).writeAsStringSync(markdown);
|
||||
return value;
|
||||
}
|
||||
final ViewPB view;
|
||||
|
||||
String _convertDocumentToMarkdown(ExportDataPB value) {
|
||||
final json = jsonDecode(value.data);
|
||||
final document = Document.fromJson(json);
|
||||
return documentToMarkdown(
|
||||
document,
|
||||
customParsers: [
|
||||
const DividerNodeParser(),
|
||||
const MathEquationNodeParser(),
|
||||
const CodeBlockNodeParser(),
|
||||
],
|
||||
Future<void> _onShareMarkdown(
|
||||
ShareMarkdown event,
|
||||
Emitter<DocShareState> emit,
|
||||
) async {
|
||||
emit(const DocShareState.loading());
|
||||
|
||||
final documentExporter = DocumentExporter(view);
|
||||
final result = await documentExporter.export(DocumentExportType.markdown);
|
||||
emit(
|
||||
DocShareState.finish(
|
||||
result.fold(
|
||||
(error) => right(error),
|
||||
(markdown) => left(_saveMarkdownToPath(markdown, event.path)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ExportDataPB _saveMarkdownToPath(String markdown, String path) {
|
||||
File(path).writeAsStringSync(markdown);
|
||||
return ExportDataPB()
|
||||
..data = markdown
|
||||
..exportType = ExportType.Markdown;
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
@ -1,32 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document2/entities.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||
|
||||
class ShareService {
|
||||
Future<Either<ExportDataPB, FlowyError>> export(
|
||||
ViewPB view,
|
||||
ExportType type,
|
||||
) {
|
||||
// var payload = ExportPayloadPB.create()
|
||||
// ..viewId = view.id
|
||||
// ..exportType = type
|
||||
// ..documentVersion = DocumentVersionPB.V1;
|
||||
|
||||
// return DocumentEventExportDocument(payload).send();
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<Either<ExportDataPB, FlowyError>> exportText(ViewPB view) {
|
||||
return export(view, ExportType.Text);
|
||||
}
|
||||
|
||||
Future<Either<ExportDataPB, FlowyError>> exportMarkdown(ViewPB view) {
|
||||
return export(view, ExportType.Markdown);
|
||||
}
|
||||
|
||||
Future<Either<ExportDataPB, FlowyError>> exportURL(ViewPB view) {
|
||||
return export(view, ExportType.Link);
|
||||
}
|
||||
}
|
@ -1,26 +1,25 @@
|
||||
library document_plugin;
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/plugins/document/application/share_bloc.dart';
|
||||
import 'package:appflowy/util/file_picker/file_picker_service.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document2/entities.pb.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:clipboard/clipboard.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DocumentShareButton extends StatelessWidget {
|
||||
const DocumentShareButton({
|
||||
super.key,
|
||||
required this.view,
|
||||
});
|
||||
|
||||
final ViewPB view;
|
||||
DocumentShareButton({Key? key, required this.view})
|
||||
: super(key: ValueKey(view.hashCode));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -28,12 +27,10 @@ class DocumentShareButton extends StatelessWidget {
|
||||
create: (context) => getIt<DocShareBloc>(param1: view),
|
||||
child: BlocListener<DocShareBloc, DocShareState>(
|
||||
listener: (context, state) {
|
||||
state.map(
|
||||
initial: (_) {},
|
||||
loading: (_) {},
|
||||
state.mapOrNull(
|
||||
finish: (state) {
|
||||
state.successOrFail.fold(
|
||||
_handleExportData,
|
||||
(data) => _handleExportData(context, data),
|
||||
_handleExportError,
|
||||
);
|
||||
},
|
||||
@ -52,27 +49,30 @@ class DocumentShareButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _handleExportData(ExportDataPB exportData) {
|
||||
void _handleExportData(BuildContext context, ExportDataPB exportData) {
|
||||
switch (exportData.exportType) {
|
||||
case ExportType.Link:
|
||||
break;
|
||||
case ExportType.Markdown:
|
||||
FlutterClipboard.copy(exportData.data)
|
||||
.then((value) => Log.info('copied to clipboard'));
|
||||
showSnackBarMessage(
|
||||
context,
|
||||
LocaleKeys.settings_files_exportFileSuccess.tr(),
|
||||
);
|
||||
break;
|
||||
case ExportType.Link:
|
||||
case ExportType.Text:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _handleExportError(FlowyError error) {}
|
||||
void _handleExportError(FlowyError error) {
|
||||
showMessageToast(error.msg);
|
||||
}
|
||||
}
|
||||
|
||||
class ShareActionList extends StatelessWidget {
|
||||
const ShareActionList({
|
||||
Key? key,
|
||||
super.key,
|
||||
required this.view,
|
||||
}) : super(key: key);
|
||||
});
|
||||
|
||||
final ViewPB view;
|
||||
|
||||
@ -94,20 +94,14 @@ class ShareActionList extends StatelessWidget {
|
||||
onSelected: (action, controller) async {
|
||||
switch (action.inner) {
|
||||
case ShareAction.markdown:
|
||||
final exportPath = await FilePicker.platform.saveFile(
|
||||
final exportPath = await getIt<FilePickerService>().saveFile(
|
||||
dialogTitle: '',
|
||||
fileName: '${view.name}.md',
|
||||
);
|
||||
if (exportPath != null) {
|
||||
docShareBloc.add(DocShareEvent.shareMarkdown(exportPath));
|
||||
showMessageToast('Exported to: $exportPath');
|
||||
}
|
||||
break;
|
||||
// case ShareAction.copyLink:
|
||||
// NavigatorAlertDialog(
|
||||
// title: LocaleKeys.shareAction_workInProgress.tr(),
|
||||
// ).show(context);
|
||||
// break;
|
||||
}
|
||||
controller.close();
|
||||
},
|
||||
@ -117,7 +111,6 @@ class ShareActionList extends StatelessWidget {
|
||||
|
||||
enum ShareAction {
|
||||
markdown,
|
||||
// copyLink,
|
||||
}
|
||||
|
||||
class ShareActionWrapper extends ActionCell {
|
||||
@ -132,8 +125,6 @@ class ShareActionWrapper extends ActionCell {
|
||||
switch (inner) {
|
||||
case ShareAction.markdown:
|
||||
return LocaleKeys.shareAction_markdown.tr();
|
||||
// case ShareAction.copyLink:
|
||||
// return LocaleKeys.shareAction_copyLink.tr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user