refactor: extracted RichEditorOptions

This commit is contained in:
jideguru 2021-06-03 12:03:20 +01:00
parent 4097c7c746
commit 0ba6803269
12 changed files with 262 additions and 140 deletions

View File

@ -34,6 +34,7 @@ Based on https://github.com/dankito/RichTextEditor, but for Flutter.
RichEditor( RichEditor(
key: keyEditor, key: keyEditor,
value: 'initial html here', value: 'initial html here',
editorOptions: RichEditorOptions(
placeholder: 'Start typing', placeholder: 'Start typing',
// backgroundColor: Colors.blueGrey, // Editor's bg color // backgroundColor: Colors.blueGrey, // Editor's bg color
// baseTextColor: Colors.white, // baseTextColor: Colors.white,
@ -43,6 +44,7 @@ Based on https://github.com/dankito/RichTextEditor, but for Flutter.
baseFontFamily: 'sans-serif', baseFontFamily: 'sans-serif',
// Position of the editing bar (BarPosition.TOP or BarPosition.BOTTOM) // Position of the editing bar (BarPosition.TOP or BarPosition.BOTTOM)
barPosition: BarPosition.TOP, barPosition: BarPosition.TOP,
),
// You can return a Link (maybe you need to upload the image to your // You can return a Link (maybe you need to upload the image to your
// storage before displaying in the editor or you can also use base64 // storage before displaying in the editor or you can also use base64
getImageUrl: (image) { getImageUrl: (image) {

94
example/lib/basic.dart Normal file
View File

@ -0,0 +1,94 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:rich_editor/rich_editor.dart';
class BasicDemo extends StatelessWidget {
GlobalKey<RichEditorState> keyEditor = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Basic Demo'),
actions: [
PopupMenuButton(
child: IconButton(
icon: Icon(Icons.more_vert),
onPressed: null,
disabledColor: Colors.white,
),
itemBuilder: (context) {
return [
PopupMenuItem(
child: Text('Get HTML'),
value: 0,
),
PopupMenuItem(
child: Text('Clear content'),
value: 1,
),
PopupMenuItem(
child: Text('Hide keyboard'),
value: 2,
),
PopupMenuItem(
child: Text('Show Keyboard'),
value: 3,
),
];
},
onSelected: (val) async {
switch (val) {
case 0:
String? html = await keyEditor.currentState?.getHtml();
print(html);
break;
case 1:
await keyEditor.currentState?.clear();
break;
case 2:
await keyEditor.currentState?.unFocus();
break;
case 3:
await keyEditor.currentState?.focus();
break;
}
},
),
],
),
body: RichEditor(
key: keyEditor,
// value: '''
// <h1>Heading 1</h1>
// <h2>Heading 2</h2>
// <h3>Heading 3</h3>
// <h4>Heading 4</h4>
// <h5>Heading 5</h5>
// <h6>Heading 6</h6>
// ''', // initial HTML data
editorOptions: RichEditorOptions(
placeholder: 'Start typing',
// backgroundColor: Colors.blueGrey, // Editor's bg color
// baseTextColor: Colors.white,
// editor padding
padding: EdgeInsets.symmetric(horizontal: 5.0),
// font name
baseFontFamily: 'sans-serif',
// Position of the editing bar (BarPosition.TOP or BarPosition.BOTTOM)
barPosition: BarPosition.TOP,
),
// You can return a Link (maybe you need to upload the image to your
// storage before displaying in the editor or you can also use base64
getImageUrl: (image) {
String link = 'https://avatars.githubusercontent.com/u/24323581?v=4';
String base64 = base64Encode(image.readAsBytesSync());
String base64String = 'data:image/png;base64, $base64';
return base64String;
},
),
);
}
}

View File

@ -0,0 +1,91 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:rich_editor/rich_editor.dart';
class CustomToolbarDemo extends StatefulWidget {
@override
_CustomToolbarDemoState createState() => _CustomToolbarDemoState();
}
class _CustomToolbarDemoState extends State<CustomToolbarDemo> {
GlobalKey<RichEditorState> keyEditor = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Custom Toolbar Demo'),
actions: [
PopupMenuButton(
child: IconButton(
icon: Icon(Icons.more_vert),
onPressed: null,
disabledColor: Colors.white,
),
itemBuilder: (context) {
return [
PopupMenuItem(
child: Text('Get HTML'),
value: 0,
),
PopupMenuItem(
child: Text('Clear content'),
value: 1,
),
PopupMenuItem(
child: Text('Hide keyboard'),
value: 2,
),
PopupMenuItem(
child: Text('Show Keyboard'),
value: 3,
),
];
},
onSelected: (val) async {
switch (val) {
case 0:
String? html = await keyEditor.currentState?.getHtml();
print(html);
break;
case 1:
await keyEditor.currentState?.clear();
break;
case 2:
await keyEditor.currentState?.unFocus();
break;
case 3:
await keyEditor.currentState?.focus();
break;
}
},
),
],
),
body: RichEditor(
key: keyEditor,
// value: '', // initial HTML data
editorOptions: RichEditorOptions(
placeholder: 'Start typing',
// backgroundColor: Colors.blueGrey, // Editor's bg color
// baseTextColor: Colors.white,
// editor padding
padding: EdgeInsets.symmetric(horizontal: 5.0),
// font name
baseFontFamily: 'sans-serif',
// Position of the editing bar (BarPosition.TOP or BarPosition.BOTTOM)
barPosition: BarPosition.TOP,
),
// You can return a Link (maybe you need to upload the image to your
// storage before displaying in the editor or you can also use base64
getImageUrl: (image) {
String link = 'https://avatars.githubusercontent.com/u/24323581?v=4';
String base64 = base64Encode(image.readAsBytesSync());
String base64String = 'data:image/png;base64, $base64';
return base64String;
},
),
);
}
}

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:example/basic.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rich_editor/rich_editor.dart'; import 'package:rich_editor/rich_editor.dart';
@ -16,102 +17,7 @@ class MyApp extends StatelessWidget {
theme: ThemeData( theme: ThemeData(
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
), ),
home: MyHomePage(title: 'Rich Editor Demo'), home: BasicDemo(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey<RichEditorState> keyEditor = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
PopupMenuButton(
child: IconButton(
icon: Icon(Icons.more_vert),
onPressed: null,
disabledColor: Colors.white,
),
itemBuilder: (context) {
return [
PopupMenuItem(
child: Text('Get HTML'),
value: 0,
),
PopupMenuItem(
child: Text('Clear content'),
value: 1,
),
PopupMenuItem(
child: Text('Hide keyboard'),
value: 2,
),
PopupMenuItem(
child: Text('Show Keyboard'),
value: 3,
),
];
},
onSelected: (val) async {
switch (val) {
case 0:
String? html = await keyEditor.currentState?.getHtml();
print(html);
break;
case 1:
await keyEditor.currentState?.clear();
break;
case 2:
await keyEditor.currentState?.unFocus();
break;
case 3:
await keyEditor.currentState?.focus();
break;
}
},
),
],
),
body: RichEditor(
key: keyEditor,
// value: '''
// <h1>Heading 1</h1>
// <h2>Heading 2</h2>
// <h3>Heading 3</h3>
// <h4>Heading 4</h4>
// <h5>Heading 5</h5>
// <h6>Heading 6</h6>
// ''', // initial HTML data
placeholder: 'Start typing',
// backgroundColor: Colors.blueGrey, // Editor's bg color
// baseTextColor: Colors.white,
// editor padding
padding: EdgeInsets.symmetric(horizontal: 5.0),
// font name
baseFontFamily: 'sans-serif',
// Position of the editing bar (BarPosition.TOP or BarPosition.BOTTOM)
barPosition: BarPosition.TOP,
// You can return a Link (maybe you need to upload the image to your
// storage before displaying in the editor or you can also use base64
getImageUrl: (image) {
String link = 'https://avatars.githubusercontent.com/u/24323581?v=4';
String base64 = base64Encode(image.readAsBytesSync());
String base64String = 'data:image/png;base64, $base64';
return base64String;
},
),
); );
} }
} }

View File

@ -1,6 +1,9 @@
library rich_editor; library rich_editor;
export 'src/models/enum/bar_position.dart';
export 'src/models/rich_editor_options.dart';
export 'src/rendering/rich_editor.dart'; export 'src/rendering/rich_editor.dart';
export 'src/utils/javascript_executor_base.dart';
export 'src/widgets/editor_tool_bar.dart'; export 'src/widgets/editor_tool_bar.dart';
export 'src/widgets/tab_button.dart'; export 'src/widgets/tab_button.dart';
export 'src/models/enum.dart'; export 'src/widgets/tab_button.dart';

View File

@ -1,6 +1,5 @@
import 'package:rich_editor/src/models/enum.dart';
import 'command_state.dart'; import 'command_state.dart';
import 'enum/command_name.dart';
class EditorState { class EditorState {
bool? didHtmlChange; bool? didHtmlChange;

View File

@ -0,0 +1 @@
enum BarPosition { TOP, BOTTOM, CUSTOM }

View File

@ -39,5 +39,3 @@ enum CommandName {
// pseudo commands for toggling grouped command views // pseudo commands for toggling grouped command views
EXPANDING_SEARCH_VIEWING, EXPANDING_SEARCH_VIEWING,
} }
enum BarPosition { TOP, BOTTOM }

View File

@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'enum/bar_position.dart';
class RichEditorOptions {
Color? backgroundColor;
Color? baseTextColor;
EdgeInsets? padding;
String? placeholder;
String? baseFontFamily;
BarPosition? barPosition;
RichEditorOptions({
Color? backgroundColor,
Color? baseTextColor,
EdgeInsets? padding,
String? placeholder,
String? baseFontFamily,
BarPosition? barPosition,
}) {
this.backgroundColor = backgroundColor;
this.baseTextColor = baseTextColor;
this.padding = padding;
this.placeholder = placeholder;
this.baseFontFamily = baseFontFamily;
this.barPosition = barPosition;
}
}

View File

@ -4,7 +4,8 @@ import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rich_editor/src/models/enum.dart'; import 'package:rich_editor/src/models/enum/bar_position.dart';
import 'package:rich_editor/src/models/rich_editor_options.dart';
import 'package:rich_editor/src/services/local_server.dart'; import 'package:rich_editor/src/services/local_server.dart';
import 'package:rich_editor/src/utils/javascript_executor_base.dart'; import 'package:rich_editor/src/utils/javascript_executor_base.dart';
import 'package:rich_editor/src/widgets/editor_tool_bar.dart'; import 'package:rich_editor/src/widgets/editor_tool_bar.dart';
@ -12,24 +13,14 @@ import 'package:webview_flutter/webview_flutter.dart';
class RichEditor extends StatefulWidget { class RichEditor extends StatefulWidget {
final String? value; final String? value;
final Color? backgroundColor; final RichEditorOptions? editorOptions;
final Color? baseTextColor;
final EdgeInsets? padding;
final String? placeholder;
final String? baseFontFamily;
final BarPosition barPosition;
final Function(File image)? getImageUrl; final Function(File image)? getImageUrl;
final Function(File video)? getVideoUrl; final Function(File video)? getVideoUrl;
RichEditor({ RichEditor({
Key? key, Key? key,
this.value, this.value,
this.backgroundColor, this.editorOptions,
this.baseTextColor,
this.padding,
this.placeholder,
this.baseFontFamily,
this.barPosition = BarPosition.TOP,
this.getImageUrl, this.getImageUrl,
this.getVideoUrl, this.getVideoUrl,
}) : super(key: key); }) : super(key: key);
@ -93,7 +84,7 @@ class RichEditorState extends State<RichEditor> {
return Column( return Column(
children: [ children: [
Visibility( Visibility(
visible: widget.barPosition == BarPosition.TOP, visible: widget.editorOptions!.barPosition == BarPosition.TOP,
child: EditorToolBar( child: EditorToolBar(
controller: _controller, controller: _controller,
getImageUrl: widget.getImageUrl, getImageUrl: widget.getImageUrl,
@ -128,7 +119,7 @@ class RichEditorState extends State<RichEditor> {
), ),
), ),
Visibility( Visibility(
visible: widget.barPosition == BarPosition.BOTTOM, visible: widget.editorOptions!.barPosition == BarPosition.BOTTOM,
child: EditorToolBar( child: EditorToolBar(
controller: _controller, controller: _controller,
getImageUrl: widget.getImageUrl, getImageUrl: widget.getImageUrl,
@ -141,16 +132,20 @@ class RichEditorState extends State<RichEditor> {
_setInitialValues() async { _setInitialValues() async {
if (widget.value != null) await javascriptExecutor.setHtml(widget.value!); if (widget.value != null) await javascriptExecutor.setHtml(widget.value!);
if (widget.padding != null) if (widget.editorOptions!.padding != null)
await javascriptExecutor.setPadding(widget.padding!); await javascriptExecutor.setPadding(widget.editorOptions!.padding!);
if (widget.backgroundColor != null) if (widget.editorOptions!.backgroundColor != null)
await javascriptExecutor.setBackgroundColor(widget.backgroundColor!); await javascriptExecutor
if (widget.baseTextColor != null) .setBackgroundColor(widget.editorOptions!.backgroundColor!);
await javascriptExecutor.setBaseTextColor(widget.baseTextColor!); if (widget.editorOptions!.baseTextColor != null)
if (widget.placeholder != null) await javascriptExecutor
await javascriptExecutor.setPlaceholder(widget.placeholder!); .setBaseTextColor(widget.editorOptions!.baseTextColor!);
if (widget.baseFontFamily != null) if (widget.editorOptions!.placeholder != null)
await javascriptExecutor.setBaseFontFamily(widget.baseFontFamily!); await javascriptExecutor
.setPlaceholder(widget.editorOptions!.placeholder!);
if (widget.editorOptions!.baseFontFamily != null)
await javascriptExecutor
.setBaseFontFamily(widget.editorOptions!.baseFontFamily!);
} }
/// Get current HTML from editor /// Get current HTML from editor

View File

@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rich_editor/src/extensions/extensions.dart'; import 'package:rich_editor/src/extensions/extensions.dart';
import 'package:rich_editor/src/models/editor_state.dart'; import 'package:rich_editor/src/models/editor_state.dart';
import 'package:rich_editor/src/models/enum.dart'; import 'package:rich_editor/src/models/enum/command_name.dart';
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
import '../models/command_state.dart'; import '../models/command_state.dart';

View File

@ -4,8 +4,9 @@ class TabButton extends StatelessWidget {
final IconData? icon; final IconData? icon;
final Function? onTap; final Function? onTap;
final String tooltip; final String tooltip;
final bool selected;
TabButton({this.icon, this.onTap, this.tooltip = ''}); TabButton({this.icon, this.onTap, this.tooltip = '', this.selected = false});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -17,7 +18,9 @@ class TabButton extends StatelessWidget {
height: 40.0, height: 40.0,
width: 40.0, width: 40.0,
decoration: BoxDecoration( decoration: BoxDecoration(
// color: Color(0xff212121), color: selected
? Theme.of(context).accentColor.withOpacity(0.2)
: Colors.transparent,
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(5.0), Radius.circular(5.0),
), ),
@ -32,7 +35,9 @@ class TabButton extends StatelessWidget {
padding: const EdgeInsets.all(5.0), padding: const EdgeInsets.all(5.0),
child: Icon( child: Icon(
icon, icon,
// color: Theme.of(context).accentColor, color: selected
? Theme.of(context).accentColor
: Theme.of(context).iconTheme.color,
), ),
), ),
), ),