| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 | import 'dart:convert';import 'dart:io';import 'package:example/plugin/underscore_to_italic.dart';import 'package:flutter/material.dart';import 'package:flutter/services.dart';import 'package:flutter_localizations/flutter_localizations.dart';import 'package:google_fonts/google_fonts.dart';import 'package:path_provider/path_provider.dart';import 'package:appflowy_editor/appflowy_editor.dart';import 'expandable_floating_action_button.dart';void main() {  runApp(const MyApp());}class MyApp extends StatelessWidget {  const MyApp({Key? key}) : super(key: key);  @override  Widget build(BuildContext context) {    return MaterialApp(      localizationsDelegates: const [        GlobalMaterialLocalizations.delegate,        GlobalCupertinoLocalizations.delegate,        GlobalWidgetsLocalizations.delegate,        AppFlowyEditorLocalizations.delegate,      ],      supportedLocales: const [Locale('en', 'US')],      debugShowCheckedModeBanner: false,      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: const MyHomePage(title: 'AppFlowyEditor Example'),    );  }}class MyHomePage extends StatefulWidget {  const MyHomePage({Key? key, required this.title}) : super(key: key);  final String title;  @override  State<MyHomePage> createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  int _pageIndex = 0;  EditorState? _editorState;  bool darkMode = false;  EditorStyle _editorStyle = EditorStyle.defaultStyle();  Future<String>? _jsonString;  @override  Widget build(BuildContext context) {    return Scaffold(      extendBodyBehindAppBar: true,      body: _buildEditor(context),      floatingActionButton: _buildExpandableFab(),    );  }  Widget _buildEditor(BuildContext context) {    if (_jsonString != null) {      return _buildEditorWithJsonString(_jsonString!);    }    if (_pageIndex == 0) {      return _buildEditorWithJsonString(        rootBundle.loadString('assets/example.json'),      );    } else if (_pageIndex == 1) {      return _buildEditorWithJsonString(        rootBundle.loadString('assets/big_document.json'),      );    } else if (_pageIndex == 2) {      return _buildEditorWithJsonString(        Future.value(          jsonEncode(EditorState.empty().document.toJson()),        ),      );    }    throw UnimplementedError();  }  Widget _buildEditorWithJsonString(Future<String> jsonString) {    return FutureBuilder<String>(      future: jsonString,      builder: (_, snapshot) {        if (snapshot.hasData &&            snapshot.connectionState == ConnectionState.done) {          _editorState ??= EditorState(            document: StateTree.fromJson(              Map<String, Object>.from(                json.decode(snapshot.data!),              ),            ),          );          _editorState!.logConfiguration            ..level = LogLevel.all            ..handler = (message) {              debugPrint(message);            };          _editorState!.operationStream.listen((event) {            debugPrint('Operation: ${event.toJson()}');          });          return Container(            color: darkMode ? Colors.black : Colors.white,            width: MediaQuery.of(context).size.width,            child: AppFlowyEditor(              editorState: _editorState!,              editorStyle: _editorStyle,              shortcutEvents: [                underscoreToItalic,              ],            ),          );        } else {          return const Center(            child: CircularProgressIndicator(),          );        }      },    );  }  Widget _buildExpandableFab() {    return ExpandableFab(      distance: 112.0,      children: [        ActionButton(          icon: const Icon(Icons.abc),          onPressed: () => _switchToPage(0),        ),        ActionButton(          icon: const Icon(Icons.abc),          onPressed: () => _switchToPage(1),        ),        ActionButton(          icon: const Icon(Icons.abc),          onPressed: () => _switchToPage(2),        ),        ActionButton(          icon: const Icon(Icons.print),          onPressed: () => _exportDocument(_editorState!),        ),        ActionButton(          icon: const Icon(Icons.import_export),          onPressed: () => _importDocument(),        ),        ActionButton(          icon: const Icon(Icons.color_lens),          onPressed: () {            setState(() {              _editorStyle =                  darkMode ? EditorStyle.defaultStyle() : _customizedStyle();              darkMode = !darkMode;            });          },        ),      ],    );  }  void _exportDocument(EditorState editorState) async {    final document = editorState.document.toJson();    final json = jsonEncode(document);    final directory = await getTemporaryDirectory();    final path = directory.path;    final file = File('$path/editor.json');    await file.writeAsString(json);    if (mounted) {      ScaffoldMessenger.of(context).showSnackBar(        SnackBar(          content: Text('The document is saved to the ${file.path}'),        ),      );    }  }  void _importDocument() async {    final directory = await getTemporaryDirectory();    final path = directory.path;    final file = File('$path/editor.json');    setState(() {      _editorState = null;      _jsonString = file.readAsString();    });  }  void _switchToPage(int pageIndex) {    if (pageIndex != _pageIndex) {      setState(() {        _editorState = null;        _pageIndex = pageIndex;      });    }  }  EditorStyle _customizedStyle() {    final editorStyle = EditorStyle.defaultStyle();    return editorStyle.copyWith(      cursorColor: Colors.white,      selectionColor: Colors.blue.withOpacity(0.3),      textStyle: editorStyle.textStyle.copyWith(        defaultTextStyle: GoogleFonts.poppins().copyWith(          color: Colors.white,          fontSize: 14.0,        ),        defaultPlaceholderTextStyle: GoogleFonts.poppins().copyWith(          color: Colors.white.withOpacity(0.5),          fontSize: 14.0,        ),        bold: const TextStyle(fontWeight: FontWeight.w900),        code: TextStyle(          fontStyle: FontStyle.italic,          color: Colors.red[300],          backgroundColor: Colors.grey.withOpacity(0.3),        ),        highlightColorHex: '0x6FFFEB3B',      ),      pluginStyles: {        'text/quote': builtInPluginStyle          ..update(            'textStyle',            (_) {              return (EditorState editorState, Node node) {                return TextStyle(                  color: Colors.blue[200],                  fontStyle: FontStyle.italic,                  fontSize: 12.0,                );              };            },          ),      },    );  }}
 |