mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-16 18:37:40 +00:00
Merge pull request #3500 from LucasXu0/fix_032_launch_review_issues
fix launch review(v0.3.3) issues
This commit is contained in:
commit
1997231adf
@ -5,6 +5,7 @@ import 'document_codeblock_paste_test.dart' as document_codeblock_paste_test;
|
|||||||
import 'document_copy_and_paste_test.dart' as document_copy_and_paste_test;
|
import 'document_copy_and_paste_test.dart' as document_copy_and_paste_test;
|
||||||
import 'document_create_and_delete_test.dart'
|
import 'document_create_and_delete_test.dart'
|
||||||
as document_create_and_delete_test;
|
as document_create_and_delete_test;
|
||||||
|
import 'document_text_direction_test.dart' as document_text_direction_test;
|
||||||
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
||||||
import 'document_with_database_test.dart' as document_with_database_test;
|
import 'document_with_database_test.dart' as document_with_database_test;
|
||||||
import 'document_with_inline_math_equation_test.dart'
|
import 'document_with_inline_math_equation_test.dart'
|
||||||
@ -29,4 +30,5 @@ void startTesting() {
|
|||||||
document_copy_and_paste_test.main();
|
document_copy_and_paste_test.main();
|
||||||
document_codeblock_paste_test.main();
|
document_codeblock_paste_test.main();
|
||||||
document_alignment_test.main();
|
document_alignment_test.main();
|
||||||
|
document_text_direction_test.main();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:appflowy/workspace/application/appearance.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
import '../util/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('text direction', () {
|
||||||
|
testWidgets(
|
||||||
|
'''no text direction items will be displayed in the default/LTR mode,and three text direction items will be displayed in the RTL mode.''',
|
||||||
|
(tester) async {
|
||||||
|
// combine the two tests into one to avoid the time-consuming process of initializing the app
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
final selection = Selection.single(
|
||||||
|
path: [0],
|
||||||
|
startOffset: 0,
|
||||||
|
endOffset: 1,
|
||||||
|
);
|
||||||
|
// click the first line of the readme
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
await tester.editor.updateSelection(selection);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// because this icons are defined in the appflowy_editor package, we can't fetch the icons by SVG data. [textDirectionItems]
|
||||||
|
final textDirectionIconNames = [
|
||||||
|
'toolbar/text_direction_auto',
|
||||||
|
'toolbar/text_direction_left',
|
||||||
|
'toolbar/text_direction_right',
|
||||||
|
];
|
||||||
|
// no text direction items in default/LTR mode
|
||||||
|
var button = find.byWidgetPredicate(
|
||||||
|
(widget) =>
|
||||||
|
widget is SVGIconItemWidget &&
|
||||||
|
textDirectionIconNames.contains(widget.iconName),
|
||||||
|
);
|
||||||
|
expect(button, findsNothing);
|
||||||
|
|
||||||
|
// switch to the RTL mode
|
||||||
|
await tester.switchLayoutDirectionMode(LayoutDirection.rtlLayout);
|
||||||
|
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
await tester.editor.updateSelection(selection);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
button = find.byWidgetPredicate(
|
||||||
|
(widget) =>
|
||||||
|
widget is SVGIconItemWidget &&
|
||||||
|
textDirectionIconNames.contains(widget.iconName),
|
||||||
|
);
|
||||||
|
expect(button, findsNWidgets(3));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/workspace/application/appearance.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_user_view.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'base.dart';
|
import 'base.dart';
|
||||||
@ -72,4 +74,35 @@ extension AppFlowySettings on WidgetTester {
|
|||||||
await testTextInput.receiveAction(TextInputAction.done);
|
await testTextInput.receiveAction(TextInputAction.done);
|
||||||
await pumpAndSettle();
|
await pumpAndSettle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go to settings page and switch the layout direction
|
||||||
|
Future<void> switchLayoutDirectionMode(
|
||||||
|
LayoutDirection layoutDirection,
|
||||||
|
) async {
|
||||||
|
await openSettings();
|
||||||
|
await openSettingsPage(SettingsPage.appearance);
|
||||||
|
|
||||||
|
final button = find.byKey(const ValueKey('layout_direction_option_button'));
|
||||||
|
expect(button, findsOneWidget);
|
||||||
|
await tapButton(button);
|
||||||
|
|
||||||
|
switch (layoutDirection) {
|
||||||
|
case LayoutDirection.ltrLayout:
|
||||||
|
final ltrButton = find.text(
|
||||||
|
LocaleKeys.settings_appearance_layoutDirection_ltr.tr(),
|
||||||
|
);
|
||||||
|
await tapButton(ltrButton);
|
||||||
|
break;
|
||||||
|
case LayoutDirection.rtlLayout:
|
||||||
|
final rtlButton = find.text(
|
||||||
|
LocaleKeys.settings_appearance_layoutDirection_rtl.tr(),
|
||||||
|
);
|
||||||
|
await tapButton(rtlButton);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tap anywhere to close the settings page
|
||||||
|
await tapAt(Offset.zero);
|
||||||
|
await pumpAndSettle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,7 +76,6 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
buildTextColorItem(),
|
buildTextColorItem(),
|
||||||
buildHighlightColorItem(),
|
buildHighlightColorItem(),
|
||||||
customizeFontToolbarItem,
|
customizeFontToolbarItem,
|
||||||
...textDirectionItems,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
late final List<SelectionMenuItem> slashMenuItems;
|
late final List<SelectionMenuItem> slashMenuItems;
|
||||||
@ -137,6 +136,9 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
convertibleBlockTypes.add(ToggleListBlockKeys.type);
|
convertibleBlockTypes.add(ToggleListBlockKeys.type);
|
||||||
slashMenuItems = _customSlashMenuItems();
|
slashMenuItems = _customSlashMenuItems();
|
||||||
effectiveScrollController = widget.scrollController ?? ScrollController();
|
effectiveScrollController = widget.scrollController ?? ScrollController();
|
||||||
|
|
||||||
|
// keep the previous font style when typing new text.
|
||||||
|
AppFlowyRichTextKeys.supportSliced.add(AppFlowyRichTextKeys.fontFamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -153,6 +155,13 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
final (bool autoFocus, Selection? selection) =
|
final (bool autoFocus, Selection? selection) =
|
||||||
_computeAutoFocusParameters();
|
_computeAutoFocusParameters();
|
||||||
|
|
||||||
|
final isRTL =
|
||||||
|
context.read<AppearanceSettingsCubit>().state.layoutDirection ==
|
||||||
|
LayoutDirection.rtlLayout;
|
||||||
|
final layoutDirection = isRTL ? TextDirection.rtl : TextDirection.ltr;
|
||||||
|
|
||||||
|
_setRTLToolbarItems(isRTL);
|
||||||
|
|
||||||
final editorScrollController = EditorScrollController(
|
final editorScrollController = EditorScrollController(
|
||||||
editorState: widget.editorState,
|
editorState: widget.editorState,
|
||||||
shrinkWrap: widget.shrinkWrap,
|
shrinkWrap: widget.shrinkWrap,
|
||||||
@ -178,12 +187,6 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
footer: const VSpace(200),
|
footer: const VSpace(200),
|
||||||
);
|
);
|
||||||
|
|
||||||
final layoutDirection =
|
|
||||||
context.read<AppearanceSettingsCubit>().state.layoutDirection ==
|
|
||||||
LayoutDirection.rtlLayout
|
|
||||||
? TextDirection.rtl
|
|
||||||
: TextDirection.ltr;
|
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: FloatingToolbar(
|
child: FloatingToolbar(
|
||||||
style: styleCustomizer.floatingToolbarStyleBuilder(),
|
style: styleCustomizer.floatingToolbarStyleBuilder(),
|
||||||
@ -463,4 +466,16 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
customizeShortcuts,
|
customizeShortcuts,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _setRTLToolbarItems(bool isRTL) {
|
||||||
|
final textDirectionItemIds = textDirectionItems.map((e) => e.id);
|
||||||
|
// clear all the text direction items
|
||||||
|
toolbarItems.removeWhere(
|
||||||
|
(item) => textDirectionItemIds.contains(item.id),
|
||||||
|
);
|
||||||
|
// only show the rtl item when the layout direction is ltr.
|
||||||
|
if (isRTL) {
|
||||||
|
toolbarItems.addAll(textDirectionItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,9 +16,11 @@ final customizeFontToolbarItem = ToolbarItem(
|
|||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
child: FontFamilyDropDown(
|
child: FontFamilyDropDown(
|
||||||
currentFontFamily: '',
|
currentFontFamily: '',
|
||||||
|
offset: const Offset(0, 12),
|
||||||
popoverController: popoverController,
|
popoverController: popoverController,
|
||||||
onOpen: () => keepEditorFocusNotifier.value += 1,
|
onOpen: () => keepEditorFocusNotifier.value += 1,
|
||||||
onClose: () => keepEditorFocusNotifier.value -= 1,
|
onClose: () => keepEditorFocusNotifier.value -= 1,
|
||||||
|
showResetButton: true,
|
||||||
onFontFamilyChanged: (fontFamily) async {
|
onFontFamilyChanged: (fontFamily) async {
|
||||||
await popoverController.close();
|
await popoverController.close();
|
||||||
try {
|
try {
|
||||||
@ -29,6 +31,9 @@ final customizeFontToolbarItem = ToolbarItem(
|
|||||||
Log.error('Failed to set font family: $e');
|
Log.error('Failed to set font family: $e');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onResetFont: () async => await editorState.formatDelta(selection, {
|
||||||
|
AppFlowyRichTextKeys.fontFamily: null,
|
||||||
|
}),
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 4.0),
|
padding: EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class LayoutDirectionSetting extends StatelessWidget {
|
|||||||
hint: LocaleKeys.settings_appearance_layoutDirection_hint.tr(),
|
hint: LocaleKeys.settings_appearance_layoutDirection_hint.tr(),
|
||||||
trailing: [
|
trailing: [
|
||||||
ThemeValueDropDown(
|
ThemeValueDropDown(
|
||||||
|
key: const ValueKey('layout_direction_option_button'),
|
||||||
currentValue: _layoutDirectionLabelText(currentLayoutDirection),
|
currentValue: _layoutDirectionLabelText(currentLayoutDirection),
|
||||||
popupBuilder: (context) => Column(
|
popupBuilder: (context) => Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|||||||
@ -60,6 +60,9 @@ class FontFamilyDropDown extends StatefulWidget {
|
|||||||
this.onFontFamilyChanged,
|
this.onFontFamilyChanged,
|
||||||
this.child,
|
this.child,
|
||||||
this.popoverController,
|
this.popoverController,
|
||||||
|
this.offset,
|
||||||
|
this.showResetButton = false,
|
||||||
|
this.onResetFont,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String currentFontFamily;
|
final String currentFontFamily;
|
||||||
@ -68,6 +71,9 @@ class FontFamilyDropDown extends StatefulWidget {
|
|||||||
final void Function(String fontFamily)? onFontFamilyChanged;
|
final void Function(String fontFamily)? onFontFamilyChanged;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final PopoverController? popoverController;
|
final PopoverController? popoverController;
|
||||||
|
final Offset? offset;
|
||||||
|
final bool showResetButton;
|
||||||
|
final VoidCallback? onResetFont;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FontFamilyDropDown> createState() => _FontFamilyDropDownState();
|
State<FontFamilyDropDown> createState() => _FontFamilyDropDownState();
|
||||||
@ -87,12 +93,20 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
query.value = '';
|
query.value = '';
|
||||||
widget.onClose?.call();
|
widget.onClose?.call();
|
||||||
},
|
},
|
||||||
|
offset: widget.offset,
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
popupBuilder: (_) {
|
popupBuilder: (_) {
|
||||||
widget.onOpen?.call();
|
widget.onOpen?.call();
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
slivers: [
|
slivers: [
|
||||||
|
if (widget.showResetButton)
|
||||||
|
SliverPersistentHeader(
|
||||||
|
delegate: _ResetFontButton(
|
||||||
|
onPressed: widget.onResetFont,
|
||||||
|
),
|
||||||
|
pinned: true,
|
||||||
|
),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: const EdgeInsets.only(right: 8),
|
padding: const EdgeInsets.only(right: 8),
|
||||||
sliver: SliverToBoxAdapter(
|
sliver: SliverToBoxAdapter(
|
||||||
@ -188,3 +202,36 @@ class _FontFamilyDropDownState extends State<FontFamilyDropDown> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ResetFontButton extends SliverPersistentHeaderDelegate {
|
||||||
|
_ResetFontButton({
|
||||||
|
this.onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(
|
||||||
|
BuildContext context,
|
||||||
|
double shrinkOffset,
|
||||||
|
bool overlapsContent,
|
||||||
|
) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8, bottom: 8.0),
|
||||||
|
child: FlowyTextButton(
|
||||||
|
LocaleKeys.document_toolbar_resetToDefaultFont.tr(),
|
||||||
|
onPressed: onPressed,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get maxExtent => 35;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get minExtent => 35;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@ class ThemeValueDropDown extends StatefulWidget {
|
|||||||
this.onClose,
|
this.onClose,
|
||||||
this.child,
|
this.child,
|
||||||
this.popoverController,
|
this.popoverController,
|
||||||
|
this.offset,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String currentValue;
|
final String currentValue;
|
||||||
@ -82,6 +83,7 @@ class ThemeValueDropDown extends StatefulWidget {
|
|||||||
final void Function()? onClose;
|
final void Function()? onClose;
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
final PopoverController? popoverController;
|
final PopoverController? popoverController;
|
||||||
|
final Offset? offset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ThemeValueDropDown> createState() => _ThemeValueDropDownState();
|
State<ThemeValueDropDown> createState() => _ThemeValueDropDownState();
|
||||||
@ -93,13 +95,14 @@ class _ThemeValueDropDownState extends State<ThemeValueDropDown> {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
key: widget.popoverKey,
|
key: widget.popoverKey,
|
||||||
controller: widget.popoverController,
|
controller: widget.popoverController,
|
||||||
direction: PopoverDirection.bottomWithRightAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
popupBuilder: widget.popupBuilder,
|
popupBuilder: widget.popupBuilder,
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
minWidth: 80,
|
minWidth: 80,
|
||||||
maxWidth: 160,
|
maxWidth: 160,
|
||||||
maxHeight: 400,
|
maxHeight: 400,
|
||||||
),
|
),
|
||||||
|
offset: widget.offset,
|
||||||
onClose: widget.onClose,
|
onClose: widget.onClose,
|
||||||
child: widget.child ??
|
child: widget.child ??
|
||||||
FlowyTextButton(
|
FlowyTextButton(
|
||||||
|
|||||||
@ -54,11 +54,11 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: a0ff609
|
ref: "8e618465258b3de0ce5253c4fa97bacb24884e8c"
|
||||||
resolved-ref: a0ff609cb1ac53e5d167489f43452074860dd80e
|
resolved-ref: "8e618465258b3de0ce5253c4fa97bacb24884e8c"
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.4.0"
|
version: "1.4.1"
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -47,7 +47,7 @@ dependencies:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: a0ff609
|
ref: 8e618465258b3de0ce5253c4fa97bacb24884e8c
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
|
|||||||
@ -647,6 +647,9 @@
|
|||||||
"label": "Link to page",
|
"label": "Link to page",
|
||||||
"tooltip": "Click to open page"
|
"tooltip": "Click to open page"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"toolbar": {
|
||||||
|
"resetToDefaultFont": "Reset to default"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"board": {
|
"board": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user