feat: support text align and block align (#3292)

* feat: support text align and block align

* test: add test
This commit is contained in:
Lucas.Xu
2023-08-30 17:21:32 +08:00
committed by GitHub
parent 897d7980f6
commit f73d59fb57
14 changed files with 241 additions and 15 deletions

View File

@ -66,6 +66,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
numberedListItem,
inlineMathEquationItem,
linkItem,
alignToolbarItem,
buildTextColorItem(),
buildHighlightColorItem(),
];

View File

@ -0,0 +1,153 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
final alignToolbarItem = ToolbarItem(
id: 'editor.align',
group: 4,
isActive: onlyShowInTextType,
builder: (context, editorState, highlightColor) {
final selection = editorState.selection!;
final nodes = editorState.getNodesInSelection(selection);
bool isSatisfyCondition(bool Function(Object? value) test) {
return nodes.every(
(n) => test(n.attributes[blockComponentAlign]),
);
}
bool isHighlight = false;
FlowySvgData data = FlowySvgs.toolbar_align_left_s;
if (isSatisfyCondition((value) => value == 'left')) {
isHighlight = true;
data = FlowySvgs.toolbar_align_left_s;
} else if (isSatisfyCondition((value) => value == 'center')) {
isHighlight = true;
data = FlowySvgs.toolbar_align_center_s;
} else if (isSatisfyCondition((value) => value == 'right')) {
isHighlight = true;
data = FlowySvgs.toolbar_align_right_s;
}
final child = FlowySvg(
data,
size: const Size.square(16),
color: isHighlight ? highlightColor : Colors.white,
);
return _AlignmentButtons(
child: child,
onAlignChanged: (align) async {
await editorState.updateNode(
selection,
(node) => node.copyWith(
attributes: {
...node.attributes,
blockComponentAlign: align,
},
),
);
},
);
},
);
class _AlignmentButtons extends StatefulWidget {
const _AlignmentButtons({
required this.child,
required this.onAlignChanged,
});
final Widget child;
final Function(String align) onAlignChanged;
@override
State<_AlignmentButtons> createState() => _AlignmentButtonsState();
}
class _AlignmentButtonsState extends State<_AlignmentButtons> {
@override
Widget build(BuildContext context) {
return AppFlowyPopover(
windowPadding: const EdgeInsets.all(0),
margin: const EdgeInsets.all(0),
direction: PopoverDirection.bottomWithCenterAligned,
offset: const Offset(0, 10),
child: widget.child,
popupBuilder: (_) => _AlignButtons(onAlignChanged: widget.onAlignChanged),
);
}
}
class _AlignButtons extends StatelessWidget {
const _AlignButtons({
required this.onAlignChanged,
});
final Function(String align) onAlignChanged;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 32,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
const HSpace(4),
_AlignButton(
icon: FlowySvgs.toolbar_align_left_s,
onTap: () => onAlignChanged('left'),
),
const _Divider(),
_AlignButton(
icon: FlowySvgs.toolbar_align_center_s,
onTap: () => onAlignChanged('center'),
),
const _Divider(),
_AlignButton(
icon: FlowySvgs.toolbar_align_right_s,
onTap: () => onAlignChanged('right'),
),
const HSpace(4),
],
),
);
}
}
class _AlignButton extends StatelessWidget {
const _AlignButton({
required this.icon,
required this.onTap,
});
final FlowySvgData icon;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: FlowySvg(
icon,
size: const Size.square(16),
),
);
}
}
class _Divider extends StatelessWidget {
const _Divider();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8),
child: Container(
width: 1,
color: Colors.grey,
),
);
}
}

View File

@ -3,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/widget/ignore_parent_gesture.dart';
import 'package:flutter/material.dart';

View File

@ -19,6 +19,7 @@ export 'image/image_menu.dart';
export 'image/image_selection_menu.dart';
export 'inline_math_equation/inline_math_equation.dart';
export 'inline_math_equation/inline_math_equation_toolbar_item.dart';
export 'align_toolbar_item/align_toolbar_item.dart';
export 'math_equation/math_equation_block_component.dart';
export 'openai/widgets/auto_completion_node_widget.dart';
export 'openai/widgets/smart_edit_node_widget.dart';

View File

@ -132,7 +132,7 @@ class _ToggleListBlockComponentWidgetState
EdgeInsets get indentPadding => configuration.indentPadding(
node,
calculateTextDirection(
defaultTextDirection: Directionality.maybeOf(context),
layoutDirection: Directionality.maybeOf(context),
),
);
@ -148,7 +148,7 @@ class _ToggleListBlockComponentWidgetState
@override
Widget buildComponent(BuildContext context) {
final textDirection = calculateTextDirection(
defaultTextDirection: Directionality.maybeOf(context),
layoutDirection: Directionality.maybeOf(context),
);
Widget child = Container(