document_page.dart 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import 'package:app_flowy/plugins/document/presentation/plugins/board/board_menu_item.dart';
  2. import 'package:app_flowy/plugins/document/presentation/plugins/board/board_node_widget.dart';
  3. import 'package:app_flowy/plugins/document/presentation/plugins/grid/grid_menu_item.dart';
  4. import 'package:app_flowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart';
  5. import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
  6. import 'package:appflowy_editor/appflowy_editor.dart';
  7. import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart';
  8. import 'package:flowy_infra_ui/widget/error_page.dart';
  9. import 'package:flutter/material.dart';
  10. import 'package:flutter_bloc/flutter_bloc.dart';
  11. import 'package:intl/intl.dart';
  12. import '../../startup/startup.dart';
  13. import 'application/doc_bloc.dart';
  14. import 'editor_styles.dart';
  15. import 'presentation/banner.dart';
  16. class DocumentPage extends StatefulWidget {
  17. final VoidCallback onDeleted;
  18. final ViewPB view;
  19. DocumentPage({
  20. required this.view,
  21. required this.onDeleted,
  22. Key? key,
  23. }) : super(key: ValueKey(view.id));
  24. @override
  25. State<DocumentPage> createState() => _DocumentPageState();
  26. }
  27. class _DocumentPageState extends State<DocumentPage> {
  28. late DocumentBloc documentBloc;
  29. final FocusNode _focusNode = FocusNode();
  30. @override
  31. void initState() {
  32. // The appflowy editor use Intl as localization, set the default language as fallback.
  33. Intl.defaultLocale = 'en_US';
  34. documentBloc = getIt<DocumentBloc>(param1: super.widget.view)
  35. ..add(const DocumentEvent.initial());
  36. super.initState();
  37. }
  38. @override
  39. Widget build(BuildContext context) {
  40. return MultiBlocProvider(
  41. providers: [
  42. BlocProvider<DocumentBloc>.value(value: documentBloc),
  43. ],
  44. child:
  45. BlocBuilder<DocumentBloc, DocumentState>(builder: (context, state) {
  46. return state.loadingState.map(
  47. loading: (_) => SizedBox.expand(
  48. child: Container(color: Colors.transparent),
  49. ),
  50. finish: (result) => result.successOrFail.fold(
  51. (_) {
  52. if (state.forceClose) {
  53. widget.onDeleted();
  54. return const SizedBox();
  55. } else {
  56. return _renderDocument(context, state);
  57. }
  58. },
  59. (err) => FlowyErrorPage(err.toString()),
  60. ),
  61. );
  62. }),
  63. );
  64. }
  65. @override
  66. Future<void> dispose() async {
  67. documentBloc.close();
  68. _focusNode.dispose();
  69. super.dispose();
  70. }
  71. Widget _renderDocument(BuildContext context, DocumentState state) {
  72. return Column(
  73. children: [
  74. if (state.isDeleted) _renderBanner(context),
  75. // AppFlowy Editor
  76. _renderAppFlowyEditor(
  77. context.read<DocumentBloc>().editorState,
  78. ),
  79. ],
  80. );
  81. }
  82. Widget _renderBanner(BuildContext context) {
  83. return DocumentBanner(
  84. onRestore: () =>
  85. context.read<DocumentBloc>().add(const DocumentEvent.restorePage()),
  86. onDelete: () => context
  87. .read<DocumentBloc>()
  88. .add(const DocumentEvent.deletePermanently()),
  89. );
  90. }
  91. Widget _renderAppFlowyEditor(EditorState editorState) {
  92. final theme = Theme.of(context);
  93. final editor = AppFlowyEditor(
  94. editorState: editorState,
  95. autoFocus: editorState.document.isEmpty,
  96. customBuilders: {
  97. // Divider
  98. kDividerType: DividerWidgetBuilder(),
  99. // Math Equation
  100. kMathEquationType: MathEquationNodeWidgetBuidler(),
  101. // Code Block
  102. kCodeBlockType: CodeBlockNodeWidgetBuilder(),
  103. // Board
  104. kBoardType: BoardNodeWidgetBuilder(),
  105. // Grid
  106. kGridType: GridNodeWidgetBuilder(),
  107. // Card
  108. kCalloutType: CalloutNodeWidgetBuilder(),
  109. },
  110. shortcutEvents: [
  111. // Divider
  112. insertDividerEvent,
  113. // Code Block
  114. enterInCodeBlock,
  115. ignoreKeysInCodeBlock,
  116. pasteInCodeBlock,
  117. ],
  118. selectionMenuItems: [
  119. // Divider
  120. dividerMenuItem,
  121. // Math Equation
  122. mathEquationMenuItem,
  123. // Code Block
  124. codeBlockMenuItem,
  125. // Emoji
  126. emojiMenuItem,
  127. // Board
  128. boardMenuItem,
  129. // Grid
  130. gridMenuItem,
  131. // Callout
  132. calloutMenuItem,
  133. ],
  134. themeData: theme.copyWith(extensions: [
  135. ...theme.extensions.values,
  136. customEditorTheme(context),
  137. ...customPluginTheme(context),
  138. ]),
  139. );
  140. return Expanded(
  141. child: Center(
  142. child: Container(
  143. constraints: const BoxConstraints(
  144. maxWidth: double.infinity,
  145. ),
  146. child: editor,
  147. ),
  148. ),
  149. );
  150. }
  151. }