feat: customize desktop toolbar style (#519)

This commit is contained in:
q200892907 2023-10-10 03:52:50 -05:00 • committed by GitHub
commit 5155663163
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 56 additions and 17 deletions

View file

@ -7,10 +7,16 @@ class FloatingToolbarStyle {
const FloatingToolbarStyle({
this.backgroundColor = Colors.black,
this.toolbarActiveColor = Colors.lightBlue,
this.toolbarIconColor = Colors.white,
this.toolbarShadowColor,
this.toolbarElevation = 0,
});
final Color backgroundColor;
final Color toolbarActiveColor;
final Color toolbarIconColor;
final Color? toolbarShadowColor;
final double toolbarElevation;
}
/// A floating toolbar that displays at the top of the editor when the selection
@ -124,6 +130,7 @@ class _FloatingToolbarState extends State<FloatingToolbar>
}
final String _debounceKey = 'show the toolbar';
void _clear() {
Debounce.cancel(_debounceKey);
@ -181,6 +188,9 @@ class _FloatingToolbarState extends State<FloatingToolbar>
editorState: editorState,
backgroundColor: widget.style.backgroundColor,
toolbarActiveColor: widget.style.toolbarActiveColor,
toolbarIconColor: widget.style.toolbarIconColor,
toolbarElevation: widget.style.toolbarElevation,
toolbarShadowColor: widget.style.toolbarShadowColor,
textDirection: widget.textDirection ?? Directionality.of(context),
);
return _toolbarWidget!;

View file

@ -15,6 +15,9 @@ class FloatingToolbarWidget extends StatefulWidget {
super.key,
this.backgroundColor = Colors.black,
required this.toolbarActiveColor,
this.toolbarIconColor,
this.toolbarElevation = 0,
this.toolbarShadowColor,
required this.items,
required this.editorState,
required this.textDirection,
@ -23,6 +26,9 @@ class FloatingToolbarWidget extends StatefulWidget {
final List<ToolbarItem> items;
final Color backgroundColor;
final Color toolbarActiveColor;
final Color? toolbarIconColor;
final double toolbarElevation;
final Color? toolbarShadowColor;
final EditorState editorState;
final TextDirection textDirection;
@ -40,6 +46,8 @@ class _FloatingToolbarWidgetState extends State<FloatingToolbarWidget> {
return Material(
borderRadius: BorderRadius.circular(8.0),
color: widget.backgroundColor,
shadowColor: widget.toolbarShadowColor,
elevation: widget.toolbarElevation,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: SizedBox(
@ -59,6 +67,7 @@ class _FloatingToolbarWidgetState extends State<FloatingToolbarWidget> {
context,
widget.editorState,
widget.toolbarActiveColor,
widget.toolbarIconColor,
),
),
)

View file

@ -31,7 +31,7 @@ class _AlignmentToolbarItem extends ToolbarItem {
id: 'editor.$id',
group: 6,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
final isHighlight = nodes.every(
@ -42,6 +42,7 @@ class _AlignmentToolbarItem extends ToolbarItem {
iconName: 'toolbar/$name',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: tooltip,
onPressed: () => editorState.updateNode(
selection,

View file

@ -4,7 +4,7 @@ final ToolbarItem bulletedListItem = ToolbarItem(
id: 'editor.bulleted_list',
group: 3,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final node = editorState.getNodeAtPath(selection.start.path)!;
final isHighlight = node.type == 'bulleted_list';
@ -12,6 +12,7 @@ final ToolbarItem bulletedListItem = ToolbarItem(
iconName: 'toolbar/bulleted_list',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.bulletedList,
onPressed: () => editorState.formatNode(
selection,

View file

@ -5,7 +5,7 @@ ToolbarItem buildHighlightColorItem({List<ColorOption>? colorOptions}) {
id: 'editor.highlightColor',
group: 4,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
String? highlightColorHex;
final selection = editorState.selection!;
@ -20,6 +20,7 @@ ToolbarItem buildHighlightColorItem({List<ColorOption>? colorOptions}) {
iconName: 'toolbar/highlight_color',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.highlightColor,
onPressed: () {
bool showClearButton = false;

View file

@ -7,7 +7,7 @@ ToolbarItem buildTextColorItem({
id: 'editor.textColor',
group: 4,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
String? textColorHex;
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
@ -21,6 +21,7 @@ ToolbarItem buildTextColorItem({
iconName: 'toolbar/text_color',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.textColor,
onPressed: () {
bool showClearButton = false;

View file

@ -43,7 +43,7 @@ class _FormatToolbarItem extends ToolbarItem {
id: 'editor.$id',
group: 2,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
@ -55,6 +55,7 @@ class _FormatToolbarItem extends ToolbarItem {
iconName: 'toolbar/$name',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: tooltip,
onPressed: () => editorState.toggleAttribute(name),
);

View file

@ -12,7 +12,7 @@ class _HeadingToolbarItem extends ToolbarItem {
id: 'editor.h$level',
group: 1,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final node = editorState.getNodeAtPath(selection.start.path)!;
final isHighlight =
@ -22,6 +22,7 @@ class _HeadingToolbarItem extends ToolbarItem {
iconName: 'toolbar/h$level',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: levelToTooltips(level),
onPressed: () => editorState.formatNode(
selection,

View file

@ -10,6 +10,7 @@ class SVGIconItemWidget extends StatelessWidget {
this.iconBuilder,
required this.isHighlight,
required this.highlightColor,
this.iconColor,
this.tooltip,
this.onPressed,
});
@ -20,6 +21,7 @@ class SVGIconItemWidget extends StatelessWidget {
final WidgetBuilder? iconBuilder;
final bool isHighlight;
final Color highlightColor;
final Color? iconColor;
final String? tooltip;
final VoidCallback? onPressed;
@ -29,7 +31,7 @@ class SVGIconItemWidget extends StatelessWidget {
? iconBuilder!(context)
: EditorSvg(
name: iconName,
color: isHighlight ? highlightColor : null,
color: isHighlight ? highlightColor : iconColor,
width: iconSize.width,
height: iconSize.height,
);

View file

@ -10,7 +10,7 @@ final linkItem = ToolbarItem(
id: 'editor.link',
group: 4,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
final isHref = nodes.allSatisfyInSelection(selection, (delta) {
@ -23,6 +23,7 @@ final linkItem = ToolbarItem(
iconName: 'toolbar/link',
isHighlight: isHref,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.link,
onPressed: () {
showLinkMenu(context, editorState, selection, isHref);

View file

@ -4,7 +4,7 @@ final ToolbarItem numberedListItem = ToolbarItem(
id: 'editor.numbered_list',
group: 3,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final node = editorState.getNodeAtPath(selection.start.path)!;
final isHighlight = node.type == 'numbered_list';
@ -12,6 +12,7 @@ final ToolbarItem numberedListItem = ToolbarItem(
iconName: 'toolbar/numbered_list',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.numberedList,
onPressed: () => editorState.formatNode(
selection,

View file

@ -4,7 +4,7 @@ final ToolbarItem paragraphItem = ToolbarItem(
id: 'editor.paragraph',
group: 1,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final node = editorState.getNodeAtPath(selection.start.path)!;
final isHighlight = node.type == 'paragraph';
@ -13,6 +13,7 @@ final ToolbarItem paragraphItem = ToolbarItem(
iconName: 'toolbar/text',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.text,
onPressed: () => editorState.formatNode(
selection,

View file

@ -7,7 +7,7 @@ final ToolbarItem placeholderItem = ToolbarItem(
id: placeholderItemId,
group: -1,
isActive: (editorState) => true,
builder: (_, __, ___) {
builder: (_, __, ___, ____) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 5),
child: Container(

View file

@ -4,7 +4,7 @@ final ToolbarItem quoteItem = ToolbarItem(
id: 'editor.quote',
group: 3,
isActive: onlyShowInSingleSelectionAndTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final node = editorState.getNodeAtPath(selection.start.path)!;
final isHighlight = node.type == 'quote';
@ -12,6 +12,7 @@ final ToolbarItem quoteItem = ToolbarItem(
iconName: 'toolbar/quote',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: AppFlowyEditorLocalizations.current.quote,
onPressed: () => editorState.formatNode(
selection,

View file

@ -31,7 +31,7 @@ class _TextDirectionToolbarItem extends ToolbarItem {
id: 'editor.$id',
group: 7,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
builder: (context, editorState, highlightColor, iconColor) {
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
final isHighlight = nodes.every(
@ -41,6 +41,7 @@ class _TextDirectionToolbarItem extends ToolbarItem {
iconName: 'toolbar/$iconName',
isHighlight: isHighlight,
highlightColor: highlightColor,
iconColor: iconColor,
tooltip: tooltip,
onPressed: () => editorState.updateNode(
selection,

View file

@ -30,6 +30,7 @@ class ToolbarItem {
BuildContext context,
EditorState editorState,
Color highlightColor,
Color? iconColor,
)? builder;
// deprecated

View file

@ -1,10 +1,9 @@
import 'package:appflowy_editor/src/editor_state.dart';
import 'package:appflowy_editor/src/flutter/overlay.dart';
import 'package:appflowy_editor/src/render/toolbar/toolbar_item.dart';
import 'package:appflowy_editor/src/render/toolbar/toolbar_item_widget.dart';
import 'package:flutter/material.dart' hide Overlay, OverlayEntry;
import 'package:appflowy_editor/src/editor_state.dart';
mixin ToolbarMixin<T extends StatefulWidget> on State<T> {
void hide();
}
@ -16,6 +15,7 @@ class ToolbarWidget extends StatefulWidget {
required this.layerLink,
required this.offset,
required this.highlightColor,
this.iconColor,
required this.items,
this.alignment = Alignment.topLeft,
}) : super(key: key);
@ -24,6 +24,7 @@ class ToolbarWidget extends StatefulWidget {
final LayerLink layerLink;
final Offset offset;
final Color highlightColor;
final Color? iconColor;
final List<ToolbarItem> items;
@ -46,7 +47,7 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
showWhenUnlinked: true,
offset: widget.offset,
followerAnchor: widget.alignment,
child: _buildToolbar(context, widget.highlightColor),
child: _buildToolbar(context, widget.highlightColor, widget.iconColor),
),
);
}
@ -57,7 +58,11 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
_listToolbarOverlay = null;
}
Widget _buildToolbar(BuildContext context, Color highlightColor) {
Widget _buildToolbar(
BuildContext context,
Color highlightColor,
Color? iconColor,
) {
return Material(
borderRadius: BorderRadius.circular(8.0),
child: Padding(
@ -73,6 +78,7 @@ class _ToolbarWidgetState extends State<ToolbarWidget> with ToolbarMixin {
context,
widget.editorState,
highlightColor,
iconColor,
) ??
item.itemBuilder?.call(context, widget.editorState) ??
ToolbarItemWidget(