fix: launch 0.7.4 review issues on desktop (#6792)

* chore: enable document test runner

* fix: double menu showing in workspace menu

* feat: only display copy in ai message

* test: add test

* test: fix integration test

* fix: rust ci
This commit is contained in:
Lucas 2024-11-15 11:12:27 +08:00 committed by GitHub
parent bced9327b1
commit 6ffb9e4d0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 117 additions and 16 deletions

View File

@ -1,6 +1,8 @@
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/uuid.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
@ -38,6 +40,10 @@ void main() {
await tester.changeWorkspaceIcon(icon);
await tester.changeWorkspaceName(name);
await tester.pumpUntilNotFound(
find.text(LocaleKeys.workspace_renameSuccess.tr()),
);
workspaceIcon = tester.widget<WorkspaceIcon>(
find.byType(WorkspaceIcon),
);

View File

@ -101,5 +101,52 @@ void main() {
final memberCount = find.text('1 member');
expect(memberCount, findsNWidgets(2));
});
testWidgets('only display one menu item in the workspace menu',
(tester) async {
// only run the test when the feature flag is on
if (!FeatureFlag.collaborativeWorkspace.isOn) {
return;
}
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.appflowyCloudSelfHost,
);
await tester.tapGoogleLoginInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
const name = 'AppFlowy.IO';
// the workspace will be opened after created
await tester.createCollaborativeWorkspace(name);
final loading = find.byType(Loading);
await tester.pumpUntilNotFound(loading);
await tester.openCollaborativeWorkspaceMenu();
// hover on the workspace and click the more button
final workspaceItem = find.byWidgetPredicate(
(w) => w is WorkspaceMenuItem && w.workspace.name == name,
);
await tester.hoverOnWidget(
workspaceItem,
onHover: () async {
final moreButton = find.byWidgetPredicate(
(w) => w is WorkspaceMoreActionList && w.workspace.name == name,
);
expect(moreButton, findsOneWidget);
await tester.tapButton(moreButton);
// click it again
await tester.tapButton(moreButton);
// nothing should happen
expect(
find.text(LocaleKeys.button_rename.tr()),
findsOneWidget,
);
},
);
});
});
}

View File

@ -1,7 +1,7 @@
import 'package:appflowy_backend/log.dart';
import 'package:integration_test/integration_test.dart';
import 'mobile/document/page_style_test.dart' as page_style_test;
import 'mobile/document/document_test_runner.dart' as document_test_runner;
import 'mobile/home_page/create_new_page_test.dart' as create_new_page_test;
import 'mobile/sign_in/anonymous_sign_in_test.dart' as anonymous_sign_in_test;
@ -16,5 +16,5 @@ Future<void> runIntegration1OnMobile() async {
anonymous_sign_in_test.main();
create_new_page_test.main();
page_style_test.main();
document_test_runner.main();
}

View File

@ -40,9 +40,13 @@ extension AppFlowyWorkspace on WidgetTester {
moreButton,
onHover: () async {
await tapButton(moreButton);
await tapButton(
find.findTextInFlowyText(LocaleKeys.button_rename.tr()),
// wait for the menu to open
final renameButton = find.findTextInFlowyText(
LocaleKeys.button_rename.tr(),
);
await pumpUntilFound(renameButton);
expect(renameButton, findsOneWidget);
await tapButton(renameButton);
final input = find.byType(TextFormField);
expect(input, findsOneWidget);
await enterText(input, name);

View File

@ -1,3 +1,4 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
import 'package:appflowy/plugins/document/presentation/editor_configuration.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
@ -5,6 +6,7 @@ import 'package:appflowy/shared/markdown_to_document.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -126,6 +128,15 @@ class _AppFlowyEditorMarkdownState extends State<_AppFlowyEditorMarkdown> {
commandShortcutEvents: [customCopyCommand],
disableAutoScroll: true,
editorState: editorState,
contextMenuItems: [
[
ContextMenuItem(
getName: LocaleKeys.document_plugins_contextMenu_copy.tr,
onPressed: (editorState) =>
customCopyCommand.execute(editorState),
),
]
],
),
);
}

View File

@ -22,9 +22,11 @@ class WorkspaceMoreActionList extends StatelessWidget {
const WorkspaceMoreActionList({
super.key,
required this.workspace,
required this.isShowingMoreActions,
});
final UserWorkspacePB workspace;
final ValueNotifier<bool> isShowingMoreActions;
@override
Widget build(BuildContext context) {
@ -46,6 +48,13 @@ class WorkspaceMoreActionList extends StatelessWidget {
.map((e) => _WorkspaceMoreActionWrapper(e, workspace))
.toList(),
constraints: const BoxConstraints(minWidth: 220),
animationDuration: Durations.short3,
slideDistance: 2,
beginScaleFactor: 1.0,
beginOpacity: 0.8,
onClosed: () {
isShowingMoreActions.value = false;
},
buildChild: (controller) {
return SizedBox.square(
dimension: 24.0,
@ -55,7 +64,11 @@ class WorkspaceMoreActionList extends StatelessWidget {
FlowySvgs.workspace_three_dots_s,
),
onTap: () {
controller.show();
if (!isShowingMoreActions.value) {
controller.show();
}
isShowingMoreActions.value = true;
},
),
);

View File

@ -25,7 +25,7 @@ const createWorkspaceButtonKey = ValueKey('createWorkspaceButton');
@visibleForTesting
const importNotionButtonKey = ValueKey('importNotinoButton');
class WorkspacesMenu extends StatelessWidget {
class WorkspacesMenu extends StatefulWidget {
const WorkspacesMenu({
super.key,
required this.userProfile,
@ -37,6 +37,19 @@ class WorkspacesMenu extends StatelessWidget {
final UserWorkspacePB currentWorkspace;
final List<UserWorkspacePB> workspaces;
@override
State<WorkspacesMenu> createState() => _WorkspacesMenuState();
}
class _WorkspacesMenuState extends State<WorkspacesMenu> {
final ValueNotifier<bool> isShowingMoreActions = ValueNotifier(false);
@override
void dispose() {
isShowingMoreActions.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
@ -72,13 +85,14 @@ class WorkspacesMenu extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
for (final workspace in workspaces) ...[
for (final workspace in widget.workspaces) ...[
WorkspaceMenuItem(
key: ValueKey(workspace.workspaceId),
workspace: workspace,
userProfile: userProfile,
isSelected:
workspace.workspaceId == currentWorkspace.workspaceId,
userProfile: widget.userProfile,
isSelected: workspace.workspaceId ==
widget.currentWorkspace.workspaceId,
isShowingMoreActions: isShowingMoreActions,
),
const VSpace(6.0),
],
@ -99,12 +113,12 @@ class WorkspacesMenu extends StatelessWidget {
}
String _getUserInfo() {
if (userProfile.email.isNotEmpty) {
return userProfile.email;
if (widget.userProfile.email.isNotEmpty) {
return widget.userProfile.email;
}
if (userProfile.name.isNotEmpty) {
return userProfile.name;
if (widget.userProfile.name.isNotEmpty) {
return widget.userProfile.name;
}
return LocaleKeys.defaultUsername.tr();
@ -117,11 +131,13 @@ class WorkspaceMenuItem extends StatefulWidget {
required this.workspace,
required this.userProfile,
required this.isSelected,
required this.isShowingMoreActions,
});
final UserProfilePB userProfile;
final UserWorkspacePB workspace;
final bool isSelected;
final ValueNotifier<bool> isShowingMoreActions;
@override
State<WorkspaceMenuItem> createState() => _WorkspaceMenuItemState();
@ -211,7 +227,10 @@ class _WorkspaceMenuItemState extends State<WorkspaceMenuItem> {
),
);
},
child: WorkspaceMoreActionList(workspace: widget.workspace),
child: WorkspaceMoreActionList(
workspace: widget.workspace,
isShowingMoreActions: widget.isShowingMoreActions,
),
),
const HSpace(8.0),
if (widget.isSelected) ...[

View File

@ -5,13 +5,14 @@ use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
use tracing::{error, trace};
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
#[allow(dead_code)]
pub struct WatchContext {
#[allow(dead_code)]
watcher: notify::RecommendedWatcher,
pub path: PathBuf,
}
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
#[allow(dead_code)]
pub fn watch_offline_app() -> FlowyResult<(WatchContext, UnboundedReceiver<WatchDiskEvent>)> {
use notify::{Event, Watcher};