import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:universal_platform/universal_platform.dart'; class MobileEditor extends StatefulWidget { const MobileEditor({ super.key, required this.editorState, this.editorStyle, }); final EditorState editorState; final EditorStyle? editorStyle; @override State createState() => _MobileEditorState(); } class _MobileEditorState extends State { EditorState get editorState => widget.editorState; late final EditorScrollController editorScrollController; late EditorStyle editorStyle; late Map blockComponentBuilders; @override void initState() { super.initState(); editorScrollController = EditorScrollController( editorState: editorState, shrinkWrap: false, ); editorStyle = _buildMobileEditorStyle(); blockComponentBuilders = _buildBlockComponentBuilders(); } @override void reassemble() { super.reassemble(); editorStyle = _buildMobileEditorStyle(); blockComponentBuilders = _buildBlockComponentBuilders(); } @override Widget build(BuildContext context) { return MobileToolbarV2( toolbarHeight: 48.0, toolbarItems: [ textDecorationMobileToolbarItemV2, buildTextAndBackgroundColorMobileToolbarItem(), blocksMobileToolbarItem, linkMobileToolbarItem, dividerMobileToolbarItem, ], editorState: editorState, child: Column( children: [ // build appflowy editor Expanded( child: MobileFloatingToolbar( editorState: editorState, editorScrollController: editorScrollController, floatingToolbarHeight: 32, toolbarBuilder: (context, anchor, closeToolbar) { return AdaptiveTextSelectionToolbar.editable( clipboardStatus: ClipboardStatus.pasteable, onCopy: () { copyCommand.execute(editorState); closeToolbar(); }, onCut: () => cutCommand.execute(editorState), onPaste: () => pasteCommand.execute(editorState), onSelectAll: () => selectAllCommand.execute(editorState), onLiveTextInput: null, onLookUp: null, onSearchWeb: null, onShare: null, anchors: TextSelectionToolbarAnchors( primaryAnchor: anchor, ), ); }, child: AppFlowyEditor( editorStyle: editorStyle, editorState: editorState, editorScrollController: editorScrollController, blockComponentBuilders: blockComponentBuilders, showMagnifier: true, // showcase 3: customize the header and footer. header: Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Image.asset( 'assets/images/header.png', ), ), footer: const SizedBox( height: 100, ), ), ), ), ], ), ); } // showcase 1: customize the editor style. EditorStyle _buildMobileEditorStyle() { return EditorStyle.mobile( textScaleFactor: 1.0, cursorColor: const Color.fromARGB(255, 134, 46, 247), dragHandleColor: const Color.fromARGB(255, 134, 46, 247), selectionColor: const Color.fromARGB(50, 134, 46, 247), textStyleConfiguration: TextStyleConfiguration( text: GoogleFonts.poppins( fontSize: 14, color: Colors.black, ), code: GoogleFonts.sourceCodePro( backgroundColor: Colors.grey.shade200, ), ), padding: const EdgeInsets.symmetric(horizontal: 24.0), magnifierSize: const Size(144, 96), mobileDragHandleBallSize: UniversalPlatform.isIOS ? const Size.square(12) : const Size.square(8), mobileDragHandleLeftExtend: 12.0, mobileDragHandleWidthExtend: 24.0, ); } // showcase 2: customize the block style Map _buildBlockComponentBuilders() { final map = { ...standardBlockComponentBuilderMap, }; // customize the heading block component final levelToFontSize = [ 24.0, 22.0, 20.0, 18.0, 16.0, 14.0, ]; map[HeadingBlockKeys.type] = HeadingBlockComponentBuilder( textStyleBuilder: (level) => GoogleFonts.poppins( fontSize: levelToFontSize.elementAtOrNull(level - 1) ?? 14.0, fontWeight: FontWeight.w600, ), ); map[ParagraphBlockKeys.type] = ParagraphBlockComponentBuilder( configuration: BlockComponentConfiguration( placeholderText: (node) => 'Type something...', ), ); return map; } }