feat: workspace settings page (#5225)

* feat: my account settings page

* test: amend tests

* chore: remove unused code

* test: remove widget tests

* fix: text color on select buttons

* test: clean and remove unused test helpers

* feat: settings workspace page

* chore: fixes after merge

* fix: recent views bugfix

* fix: make sure text buttons have color

* test: add test for delete workspace in settings

* test: remove pumpAndSettle for create workspace

* test: longer pump duration

* test: attempt with large pump duration

* test: attempt workaround

* chore: clean code

* fix: missing language key

* test: add one more check

* test: pump

* test: more pump

* test: attempt pumpAndSettle

* chore: code review

* fix: persist single workspace on patch

* fix: listen to workspace changes

* chore: remove redundant builder

* test: remove unstable test

* fix: changes after merge

* chore: changes after merge

* feat: support changing cursor and selection color

* chore: move members up in menu

* feat: clean code and beautify dialogs

* fix: fix test and make show selected font

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
Mathias Mogensen
2024-05-10 16:08:32 +02:00
committed by GitHub
parent f47c88b022
commit a0ed043cb8
77 changed files with 3434 additions and 1825 deletions

View File

@ -60,9 +60,12 @@ void main() {
Finder success;
final Finder items = find.byType(WorkspaceMenuItem);
// delete the newly created workspace
await tester.openCollaborativeWorkspaceMenu();
final Finder items = find.byType(WorkspaceMenuItem);
await tester.pumpUntilFound(items);
expect(items, findsNWidgets(2));
expect(
tester.widget<WorkspaceMenuItem>(items.last).workspace.name,

View File

@ -1,11 +1,9 @@
import 'package:integration_test/integration_test.dart';
import 'notifications_settings_test.dart' as notifications_settings_test;
import 'user_language_test.dart' as user_language_test;
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
notifications_settings_test.main();
user_language_test.main();
}

View File

@ -1,70 +0,0 @@
import 'dart:ui';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('Settings: user language tests', () {
testWidgets('select language, language changed', (tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.language);
final userLanguageFinder = find.descendant(
of: find.byType(SettingsLanguageView),
matching: find.byType(LanguageSelector),
);
// Grab current locale
LanguageSelector userLanguage =
tester.widget<LanguageSelector>(userLanguageFinder);
Locale currentLocale = userLanguage.currentLocale;
// Open language selector
await tester.tap(userLanguageFinder);
await tester.pumpAndSettle();
// Select first option that isn't default
await tester.tap(find.byType(LanguageItem).at(1));
await tester.pumpAndSettle();
// Make sure the new locale is not the same as previous one
userLanguage = tester.widget<LanguageSelector>(userLanguageFinder);
expect(
userLanguage.currentLocale,
isNot(equals(currentLocale)),
reason: "new language shouldn't equal the previous selected language",
);
// Update the current locale to a new one
currentLocale = userLanguage.currentLocale;
// Tried the same flow for the second time
// Open language selector
await tester.tap(userLanguageFinder);
await tester.pumpAndSettle();
// Select second option that isn't default
await tester.tap(find.byType(LanguageItem).at(2));
await tester.pumpAndSettle();
// Make sure the new locale is not the same as previous one
userLanguage = tester.widget<LanguageSelector>(userLanguageFinder);
expect(
userLanguage.currentLocale,
isNot(equals(currentLocale)),
reason: "new language shouldn't equal the previous selected language",
);
});
});
}

View File

@ -1,93 +0,0 @@
import 'package:appflowy/util/font_family_extension.dart';
import 'package:appflowy/workspace/application/appearance_defaults.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/settings_appearance.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('appearance settings tests', () {
testWidgets('after editing text field, button should be able to be clicked',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.appearance);
final dropDown = find.byKey(ThemeFontFamilySetting.popoverKey);
await tester.tap(dropDown);
await tester.pumpAndSettle();
final textField = find.byKey(ThemeFontFamilySetting.textFieldKey);
await tester.tap(textField);
await tester.pumpAndSettle();
await tester.enterText(textField, 'Abel');
await tester.pumpAndSettle();
final fontFamilyButton = find.byKey(const Key('Abel'));
expect(fontFamilyButton, findsOneWidget);
await tester.tap(fontFamilyButton);
await tester.pumpAndSettle();
// just switch the page and verify that the font family was set after that
await tester.openSettingsPage(SettingsPage.files);
await tester.openSettingsPage(SettingsPage.appearance);
expect(find.textContaining('Abel'), findsOneWidget);
});
testWidgets('reset the font family', (tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.appearance);
final dropDown = find.byKey(ThemeFontFamilySetting.popoverKey);
await tester.tap(dropDown);
await tester.pumpAndSettle();
final textField = find.byKey(ThemeFontFamilySetting.textFieldKey);
await tester.tap(textField);
await tester.pumpAndSettle();
await tester.enterText(textField, 'Abel');
await tester.pumpAndSettle();
final fontFamilyButton = find.byKey(const Key('Abel'));
expect(fontFamilyButton, findsOneWidget);
await tester.tap(fontFamilyButton);
await tester.pumpAndSettle();
// just switch the page and verify that the font family was set after that
await tester.openSettingsPage(SettingsPage.files);
await tester.openSettingsPage(SettingsPage.appearance);
final resetButton = find.byKey(ThemeFontFamilySetting.resetButtonKey);
await tester.tap(resetButton);
await tester.pumpAndSettle();
// just switch the page and verify that the font family was set after that
await tester.openSettingsPage(SettingsPage.files);
await tester.openSettingsPage(SettingsPage.appearance);
expect(
find.textContaining(
DefaultAppearanceSettings.kDefaultFontFamily.fontFamilyDisplayName,
),
findsNWidgets(2),
);
});
});
}

View File

@ -1,11 +1,13 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar.dart';
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
@ -23,31 +25,35 @@ void main() {
await tester.expectToSeeHomePageWithGetStartedPage();
await tester.openSettings();
await tester.openSettingsPage(SettingsPage.appearance);
await tester.openSettingsPage(SettingsPage.workspace);
await tester.pumpAndSettle();
tester.expectToSeeText(
LocaleKeys.settings_appearance_themeMode_system.tr(),
);
final appFinder = find.byType(MaterialApp).first;
ThemeMode? themeMode = tester.widget<MaterialApp>(appFinder).themeMode;
expect(themeMode, ThemeMode.system);
await tester.tapButton(
find.bySemanticsLabel(
LocaleKeys.settings_appearance_themeMode_system.tr(),
LocaleKeys.settings_workspacePage_appearance_options_light.tr(),
),
);
await tester.pumpAndSettle();
themeMode = tester.widget<MaterialApp>(appFinder).themeMode;
expect(themeMode, ThemeMode.light);
await tester.tapButton(
find.bySemanticsLabel(
LocaleKeys.settings_appearance_themeMode_dark.tr(),
LocaleKeys.settings_workspacePage_appearance_options_dark.tr(),
),
);
await tester.pumpAndSettle();
await tester.pumpAndSettle(const Duration(seconds: 1));
themeMode = tester.widget<MaterialApp>(appFinder).themeMode;
expect(themeMode, ThemeMode.dark);
await tester.tap(find.byType(SettingsDialog));
await tester.pumpAndSettle();
await FlowyTestKeyboard.simulateKeyDownEvent(
@ -60,12 +66,10 @@ void main() {
],
tester: tester,
);
await tester.pumpAndSettle();
tester.expectToSeeText(
LocaleKeys.settings_appearance_themeMode_light.tr(),
);
themeMode = tester.widget<MaterialApp>(appFinder).themeMode;
expect(themeMode, ThemeMode.light);
});
testWidgets('show or hide home menu', (tester) async {

View File

@ -1,4 +1,4 @@
import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart';
import 'package:appflowy/user/presentation/screens/skip_log_in_screen.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

View File

@ -3,8 +3,6 @@ import 'package:integration_test/integration_test.dart';
import 'desktop/board/board_test_runner.dart' as board_test_runner;
import 'desktop/settings/settings_runner.dart' as settings_test_runner;
import 'desktop/sidebar/sidebar_test_runner.dart' as sidebar_test_runner;
import 'desktop/uncategorized/appearance_settings_test.dart'
as appearance_test_runner;
import 'desktop/uncategorized/emoji_shortcut_test.dart' as emoji_shortcut_test;
import 'desktop/uncategorized/empty_test.dart' as first_test;
import 'desktop/uncategorized/hotkeys_test.dart' as hotkeys_test;
@ -26,7 +24,6 @@ Future<void> runIntegration3OnDesktop() async {
emoji_shortcut_test.main();
hotkeys_test.main();
emoji_shortcut_test.main();
appearance_test_runner.main();
settings_test_runner.main();
share_markdown_test.main();
import_files_test.main();

View File

@ -173,27 +173,39 @@ extension AppFlowyTestBase on WidgetTester {
int buttons = kPrimaryButton,
bool warnIfMissed = false,
int milliseconds = 500,
bool pumpAndSettle = true,
}) async {
await tap(
finder,
buttons: buttons,
warnIfMissed: warnIfMissed,
);
await pumpAndSettle(
Duration(milliseconds: milliseconds),
EnginePhase.sendSemanticsUpdate,
const Duration(seconds: 5),
);
if (pumpAndSettle) {
await this.pumpAndSettle(
Duration(milliseconds: milliseconds),
EnginePhase.sendSemanticsUpdate,
const Duration(seconds: 5),
);
}
}
Future<void> tapButtonWithName(String tr, {int milliseconds = 500}) async {
Future<void> tapButtonWithName(
String tr, {
int milliseconds = 500,
bool pumpAndSettle = true,
}) async {
Finder button = find.text(tr, findRichText: true, skipOffstage: false);
if (button.evaluate().isEmpty) {
button = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.text == tr,
);
}
await tapButton(button, milliseconds: milliseconds);
await tapButton(
button,
milliseconds: milliseconds,
pumpAndSettle: pumpAndSettle,
);
}
Future<void> doubleTapAt(

View File

@ -22,7 +22,6 @@ import 'package:appflowy/workspace/presentation/notifications/widgets/flowy_tab.
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_button.dart';
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_tab_bar.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart';
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
@ -511,8 +510,9 @@ extension CommonOperations on WidgetTester {
final workspace = find.byType(SidebarWorkspace);
expect(workspace, findsOneWidget);
// click it
await tapButton(workspace, milliseconds: 2000);
await tapButton(workspace, pumpAndSettle: false);
await pump(const Duration(seconds: 5));
}
Future<void> createCollaborativeWorkspace(String name) async {
@ -527,7 +527,8 @@ extension CommonOperations on WidgetTester {
// click the create button
final createButton = find.byKey(createWorkspaceButtonKey);
expect(createButton, findsOneWidget);
await tapButton(createButton);
await tapButton(createButton, pumpAndSettle: false);
await pump(const Duration(seconds: 5));
// see the create workspace dialog
final createWorkspaceDialog = find.byType(CreateWorkspaceDialog);
@ -536,7 +537,8 @@ extension CommonOperations on WidgetTester {
// input the workspace name
await enterText(find.byType(TextField), name);
await tapButtonWithName(LocaleKeys.button_ok.tr());
await tapButtonWithName(LocaleKeys.button_ok.tr(), pumpAndSettle: false);
await pump(const Duration(seconds: 5));
}
// For mobile platform to launch the app in anonymous mode

View File

@ -3,9 +3,10 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
import 'package:appflowy/workspace/presentation/settings/pages/settings_account_view.dart';
import 'package:appflowy/workspace/presentation/settings/pages/settings_workspace_view.dart';
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/text_field.dart';
import 'package:flutter_test/flutter_test.dart';
@ -13,6 +14,7 @@ import 'package:flutter_test/flutter_test.dart';
import '../desktop/board/board_hide_groups_test.dart';
import 'base.dart';
import 'common_operations.dart';
extension AppFlowySettings on WidgetTester {
/// Open settings page
@ -77,12 +79,21 @@ extension AppFlowySettings on WidgetTester {
// go to settings page and toggle enable RTL toolbar items
Future<void> toggleEnableRTLToolbarItems() async {
await openSettings();
await openSettingsPage(SettingsPage.appearance);
await openSettingsPage(SettingsPage.workspace);
final switchButton =
find.byKey(EnableRTLToolbarItemsSetting.enableRTLSwitchKey);
expect(switchButton, findsOneWidget);
await tapButton(switchButton);
final scrollable = find.findSettingsScrollable();
await scrollUntilVisible(
find.byType(EnableRTLItemsSwitcher),
0,
scrollable: scrollable,
);
final switcher = find.descendant(
of: find.byType(EnableRTLItemsSwitcher),
matching: find.byType(Toggle),
);
await tap(switcher);
// tap anywhere to close the settings page
await tapAt(Offset.zero);