mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-12-05 03:23:12 +00:00
feat: support table align on desktop (#7034)
* feat: support table align on desktop * test: update table align * test: add integration test
This commit is contained in:
parent
6e0534400b
commit
20bff9003e
@ -561,6 +561,72 @@ void main() {
|
||||
final node = editorState.document.nodeAtPath([0, 0, 0])!;
|
||||
expect(node.children.length, 1);
|
||||
});
|
||||
|
||||
testWidgets('using option menu to set table align', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapAnonymousSignInButton();
|
||||
await tester.createNewPageWithNameUnderParent(
|
||||
name: 'simple_table_test',
|
||||
);
|
||||
|
||||
await tester.editor.tapLineOfEditorAt(0);
|
||||
await tester.insertTableInDocument();
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
|
||||
final editorState = tester.editor.getCurrentEditorState();
|
||||
final beforeAlign = editorState.document.nodeAtPath([0])!.tableAlign;
|
||||
expect(beforeAlign, TableAlign.left);
|
||||
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_simpleTable_moreActions_align.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_optionAction_center.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final afterAlign = editorState.document.nodeAtPath([0])!.tableAlign;
|
||||
expect(afterAlign, TableAlign.center);
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_simpleTable_moreActions_align.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_optionAction_right.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final afterAlign2 = editorState.document.nodeAtPath([0])!.tableAlign;
|
||||
expect(afterAlign2, TableAlign.right);
|
||||
|
||||
await tester.editor.hoverAndClickOptionMenuButton([0]);
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_simpleTable_moreActions_align.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tapButton(
|
||||
find.text(
|
||||
LocaleKeys.document_plugins_optionAction_left.tr(),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final afterAlign3 = editorState.document.nodeAtPath([0])!.tableAlign;
|
||||
expect(afterAlign3, TableAlign.left);
|
||||
});
|
||||
}
|
||||
|
||||
extension on WidgetTester {
|
||||
|
||||
@ -126,6 +126,14 @@ List<OptionAction> _buildOptionActions(BuildContext context, String type) {
|
||||
|
||||
standardActions.add(OptionAction.turnInto);
|
||||
|
||||
if (SimpleTableBlockKeys.type == type) {
|
||||
standardActions.addAll([
|
||||
OptionAction.divider,
|
||||
OptionAction.setToPageWidth,
|
||||
OptionAction.distributeColumnsEvenly,
|
||||
]);
|
||||
}
|
||||
|
||||
if (EditorOptionActionType.color.supportTypes.contains(type)) {
|
||||
standardActions.addAll([OptionAction.divider, OptionAction.color]);
|
||||
}
|
||||
@ -138,14 +146,6 @@ List<OptionAction> _buildOptionActions(BuildContext context, String type) {
|
||||
standardActions.addAll([OptionAction.divider, OptionAction.depth]);
|
||||
}
|
||||
|
||||
if (SimpleTableBlockKeys.type == type) {
|
||||
standardActions.addAll([
|
||||
OptionAction.divider,
|
||||
OptionAction.setToPageWidth,
|
||||
OptionAction.distributeColumnsEvenly,
|
||||
]);
|
||||
}
|
||||
|
||||
return standardActions;
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/simple_table/simple_table.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
enum OptionAlignType {
|
||||
left,
|
||||
@ -58,8 +58,8 @@ class AlignOptionAction extends PopoverActionCell {
|
||||
Widget? leftIcon(Color iconColor) {
|
||||
return FlowySvg(
|
||||
align.svg,
|
||||
size: const Size.square(12),
|
||||
).padding(all: 2.0);
|
||||
size: const Size.square(18),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -102,7 +102,11 @@ class AlignOptionAction extends PopoverActionCell {
|
||||
return HoverButton(
|
||||
onTap: () => onTap(e.inner),
|
||||
itemHeight: ActionListSizes.itemHeight,
|
||||
leftIcon: leftIcon,
|
||||
leftIcon: SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: leftIcon,
|
||||
),
|
||||
name: e.name,
|
||||
rightIcon: rightIcon,
|
||||
);
|
||||
@ -115,7 +119,9 @@ class AlignOptionAction extends PopoverActionCell {
|
||||
return OptionAlignType.center;
|
||||
}
|
||||
final node = editorState.getNodeAtPath(selection.start.path);
|
||||
final align = node?.attributes[blockComponentAlign];
|
||||
final align = node?.type == SimpleTableBlockKeys.type
|
||||
? node?.tableAlign.key
|
||||
: node?.attributes[blockComponentAlign];
|
||||
return OptionAlignType.fromString(align);
|
||||
}
|
||||
|
||||
@ -131,11 +137,20 @@ class AlignOptionAction extends PopoverActionCell {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
final transaction = editorState.transaction;
|
||||
transaction.updateNode(node, {
|
||||
blockComponentAlign: align.name,
|
||||
});
|
||||
await editorState.apply(transaction);
|
||||
// the align attribute for simple table is not same as the align type,
|
||||
// so we need to convert the align type to the align attribute
|
||||
if (node.type == SimpleTableBlockKeys.type) {
|
||||
await editorState.updateTableAlign(
|
||||
tableNode: node,
|
||||
align: TableAlign.fromString(align.name),
|
||||
);
|
||||
} else {
|
||||
final transaction = editorState.transaction;
|
||||
transaction.updateNode(node, {
|
||||
blockComponentAlign: align.name,
|
||||
});
|
||||
await editorState.apply(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ enum EditorOptionActionType {
|
||||
case EditorOptionActionType.align:
|
||||
return {
|
||||
ImageBlockKeys.type,
|
||||
SimpleTableBlockKeys.type,
|
||||
};
|
||||
case EditorOptionActionType.depth:
|
||||
return {
|
||||
|
||||
@ -348,7 +348,9 @@ class SimpleTableCellBlockWidgetState extends State<SimpleTableCellBlockWidget>
|
||||
|
||||
Widget _buildTableActionMenu() {
|
||||
final tableNode = node.parentTableNode;
|
||||
if (tableNode == null) {
|
||||
|
||||
// the table action menu is only available on mobile platform.
|
||||
if (tableNode == null || UniversalPlatform.isDesktop) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,13 @@ enum TableAlign {
|
||||
center,
|
||||
right;
|
||||
|
||||
static TableAlign fromString(String align) {
|
||||
return TableAlign.values.firstWhere(
|
||||
(e) => e.key.toLowerCase() == align.toLowerCase(),
|
||||
orElse: () => TableAlign.left,
|
||||
);
|
||||
}
|
||||
|
||||
String get name => switch (this) {
|
||||
TableAlign.left => 'Left',
|
||||
TableAlign.center => 'Center',
|
||||
@ -808,4 +815,38 @@ extension TableNodeExtension on Node {
|
||||
}
|
||||
return children.last.getLastChildIndex();
|
||||
}
|
||||
|
||||
/// Get table align of column
|
||||
///
|
||||
/// If one of the align is not same as the others, it will return TableAlign.left.
|
||||
TableAlign get allColumnAlign {
|
||||
final alignSet = columnAligns.values.toSet();
|
||||
if (alignSet.length == 1) {
|
||||
return TableAlign.fromString(alignSet.first);
|
||||
}
|
||||
return TableAlign.left;
|
||||
}
|
||||
|
||||
/// Get table align of row
|
||||
///
|
||||
/// If one of the align is not same as the others, it will return TableAlign.left.
|
||||
TableAlign get allRowAlign {
|
||||
final alignSet = rowAligns.values.toSet();
|
||||
if (alignSet.length == 1) {
|
||||
return TableAlign.fromString(alignSet.first);
|
||||
}
|
||||
return TableAlign.left;
|
||||
}
|
||||
|
||||
/// Get table align of the table.
|
||||
///
|
||||
/// If one of the align is not same as the others, it will return TableAlign.left.
|
||||
TableAlign get tableAlign {
|
||||
if (allColumnAlign != TableAlign.left) {
|
||||
return allColumnAlign;
|
||||
} else if (allRowAlign != TableAlign.left) {
|
||||
return allRowAlign;
|
||||
}
|
||||
return TableAlign.left;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +173,8 @@ extension TableOptionOperation on EditorState {
|
||||
for (var i = 0; i < tableNode.columnLength; i++) {
|
||||
attributes = attributes.mergeValues(
|
||||
SimpleTableBlockKeys.columnAligns,
|
||||
attributes[SimpleTableBlockKeys.columnAligns],
|
||||
attributes[SimpleTableBlockKeys.columnAligns] ??
|
||||
SimpleTableColumnAlignMap(),
|
||||
duplicatedEntry: MapEntry(i.toString(), align.key),
|
||||
);
|
||||
}
|
||||
|
||||
@ -174,5 +174,24 @@ void main() {
|
||||
'1': '0xFF0000FF',
|
||||
});
|
||||
});
|
||||
|
||||
test('update table align', () async {
|
||||
final (editorState, tableNode) = createEditorStateAndTable(
|
||||
rowCount: 2,
|
||||
columnCount: 3,
|
||||
);
|
||||
|
||||
for (final align in [
|
||||
TableAlign.center,
|
||||
TableAlign.right,
|
||||
TableAlign.left,
|
||||
]) {
|
||||
await editorState.updateTableAlign(
|
||||
tableNode: tableNode,
|
||||
align: align,
|
||||
);
|
||||
expect(tableNode.tableAlign, align);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user