mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-01 10:33:29 +00:00
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:
parent
bced9327b1
commit
6ffb9e4d0f
@ -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),
|
||||
);
|
||||
|
||||
@ -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,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@ -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) ...[
|
||||
|
||||
@ -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};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user