mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: cannot click on links (#3017)
This commit is contained in:
parent
1f720efc8a
commit
706a5e784f
@ -8,7 +8,6 @@ import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import 'util/database_test_op.dart';
|
||||
import 'util/emoji.dart';
|
||||
import 'util/ime.dart';
|
||||
import 'util/util.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -9,6 +9,7 @@ import 'document_with_inline_math_equation_test.dart'
|
||||
import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
||||
import 'document_with_toggle_list_test.dart' as document_with_toggle_list_test;
|
||||
import 'edit_document_test.dart' as document_edit_test;
|
||||
import 'document_with_outline_block_test.dart' as document_with_outline_block;
|
||||
|
||||
void startTesting() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
@ -20,5 +21,6 @@ void startTesting() {
|
||||
document_with_inline_page_test.main();
|
||||
document_with_inline_math_equation_test.main();
|
||||
document_with_cover_image_test.main();
|
||||
document_with_outline_block.main();
|
||||
document_with_toggle_list_test.main();
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../util/ime.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -0,0 +1,85 @@
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('test editing link in document', () {
|
||||
late MockUrlLauncher mock;
|
||||
|
||||
setUp(() {
|
||||
mock = MockUrlLauncher();
|
||||
UrlLauncherPlatform.instance = mock;
|
||||
});
|
||||
|
||||
testWidgets('insert/edit/open link', (tester) async {
|
||||
await tester.initializeAppFlowy();
|
||||
await tester.tapGoButton();
|
||||
|
||||
// create a new document
|
||||
await tester.createNewPageWithName(
|
||||
ViewLayoutPB.Document,
|
||||
);
|
||||
|
||||
// tap the first line of the document
|
||||
await tester.editor.tapLineOfEditorAt(0);
|
||||
// insert a inline page
|
||||
const link = 'AppFlowy';
|
||||
await tester.ime.insertText(link);
|
||||
await tester.editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0, endOffset: link.length),
|
||||
);
|
||||
|
||||
// tap the link button
|
||||
final linkButton = find.byTooltip(
|
||||
'Link',
|
||||
);
|
||||
await tester.tapButton(linkButton);
|
||||
expect(find.text('Add your link', findRichText: true), findsOneWidget);
|
||||
|
||||
// input the link
|
||||
const url = 'https://appflowy.io';
|
||||
final textField = find.byWidgetPredicate(
|
||||
(widget) => widget is TextField && widget.decoration!.hintText == 'URL',
|
||||
);
|
||||
await tester.enterText(textField, url);
|
||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// single-click the link menu to show the menu
|
||||
await tester.tapButton(find.text(link, findRichText: true));
|
||||
expect(find.text('Open link', findRichText: true), findsOneWidget);
|
||||
expect(find.text('Copy link', findRichText: true), findsOneWidget);
|
||||
expect(find.text('Remove link', findRichText: true), findsOneWidget);
|
||||
|
||||
// double-click the link menu to open the link
|
||||
mock
|
||||
..setLaunchExpectations(
|
||||
url: url,
|
||||
useSafariVC: false,
|
||||
useWebView: false,
|
||||
universalLinksOnly: false,
|
||||
enableJavaScript: true,
|
||||
enableDomStorage: true,
|
||||
headers: <String, String>{},
|
||||
webOnlyWindowName: null,
|
||||
launchMode: PreferredLaunchMode.platformDefault,
|
||||
)
|
||||
..setResponse(true);
|
||||
|
||||
await tester.simulateKeyEvent(LogicalKeyboardKey.escape);
|
||||
await tester.doubleTapAt(
|
||||
tester.getTopLeft(find.text(link, findRichText: true)).translate(5, 5),
|
||||
);
|
||||
expect(mock.canLaunchCalled, isTrue);
|
||||
expect(mock.launchCalled, isTrue);
|
||||
});
|
||||
});
|
||||
}
|
@ -5,7 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../util/ime.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
@ -8,7 +8,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../util/ime.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -6,7 +6,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:integration_test/integration_test.dart';
|
||||
|
||||
import '../util/ime.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
void main() {
|
||||
|
@ -12,7 +12,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'ime.dart';
|
||||
import 'util.dart';
|
||||
|
||||
extension EditorWidgetTester on WidgetTester {
|
||||
|
@ -0,0 +1,110 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
import 'package:url_launcher_platform_interface/link.dart';
|
||||
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
|
||||
|
||||
class MockUrlLauncher extends Fake
|
||||
with MockPlatformInterfaceMixin
|
||||
implements UrlLauncherPlatform {
|
||||
String? url;
|
||||
PreferredLaunchMode? launchMode;
|
||||
bool? useSafariVC;
|
||||
bool? useWebView;
|
||||
bool? enableJavaScript;
|
||||
bool? enableDomStorage;
|
||||
bool? universalLinksOnly;
|
||||
Map<String, String>? headers;
|
||||
String? webOnlyWindowName;
|
||||
|
||||
bool? response;
|
||||
|
||||
bool closeWebViewCalled = false;
|
||||
bool canLaunchCalled = false;
|
||||
bool launchCalled = false;
|
||||
|
||||
// ignore: use_setters_to_change_properties
|
||||
void setCanLaunchExpectations(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
void setLaunchExpectations({
|
||||
required String url,
|
||||
PreferredLaunchMode? launchMode,
|
||||
bool? useSafariVC,
|
||||
bool? useWebView,
|
||||
required bool enableJavaScript,
|
||||
required bool enableDomStorage,
|
||||
required bool universalLinksOnly,
|
||||
required Map<String, String> headers,
|
||||
required String? webOnlyWindowName,
|
||||
}) {
|
||||
this.url = url;
|
||||
this.launchMode = launchMode;
|
||||
this.useSafariVC = useSafariVC;
|
||||
this.useWebView = useWebView;
|
||||
this.enableJavaScript = enableJavaScript;
|
||||
this.enableDomStorage = enableDomStorage;
|
||||
this.universalLinksOnly = universalLinksOnly;
|
||||
this.headers = headers;
|
||||
this.webOnlyWindowName = webOnlyWindowName;
|
||||
}
|
||||
|
||||
// ignore: use_setters_to_change_properties
|
||||
void setResponse(bool response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@override
|
||||
LinkDelegate? get linkDelegate => null;
|
||||
|
||||
@override
|
||||
Future<bool> canLaunch(String url) async {
|
||||
expect(url, this.url);
|
||||
canLaunchCalled = true;
|
||||
return response!;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> launch(
|
||||
String url, {
|
||||
required bool useSafariVC,
|
||||
required bool useWebView,
|
||||
required bool enableJavaScript,
|
||||
required bool enableDomStorage,
|
||||
required bool universalLinksOnly,
|
||||
required Map<String, String> headers,
|
||||
String? webOnlyWindowName,
|
||||
}) async {
|
||||
expect(url, this.url);
|
||||
expect(useSafariVC, this.useSafariVC);
|
||||
expect(useWebView, this.useWebView);
|
||||
expect(enableJavaScript, this.enableJavaScript);
|
||||
expect(enableDomStorage, this.enableDomStorage);
|
||||
expect(universalLinksOnly, this.universalLinksOnly);
|
||||
expect(headers, this.headers);
|
||||
expect(webOnlyWindowName, this.webOnlyWindowName);
|
||||
launchCalled = true;
|
||||
return response!;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> launchUrl(String url, LaunchOptions options) async {
|
||||
expect(url, this.url);
|
||||
expect(options.mode, launchMode);
|
||||
expect(options.webViewConfiguration.enableJavaScript, enableJavaScript);
|
||||
expect(options.webViewConfiguration.enableDomStorage, enableDomStorage);
|
||||
expect(options.webViewConfiguration.headers, headers);
|
||||
expect(options.webOnlyWindowName, webOnlyWindowName);
|
||||
launchCalled = true;
|
||||
return response!;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> closeWebView() async {
|
||||
closeWebViewCalled = true;
|
||||
}
|
||||
}
|
@ -4,3 +4,5 @@ export 'settings.dart';
|
||||
export 'data.dart';
|
||||
export 'expectation.dart';
|
||||
export 'editor_test_operations.dart';
|
||||
export 'mock/mock_url_launcher.dart';
|
||||
export 'ime.dart';
|
||||
|
@ -357,6 +357,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
||||
outlineItem,
|
||||
mathEquationItem,
|
||||
codeBlockItem,
|
||||
toggleListBlockItem,
|
||||
emojiMenuItem,
|
||||
autoGeneratorMenuItem,
|
||||
];
|
||||
|
@ -1,4 +1,6 @@
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -42,6 +44,15 @@ Node toggleListBlockNode({
|
||||
);
|
||||
}
|
||||
|
||||
// defining the toggle list block menu item
|
||||
SelectionMenuItem toggleListBlockItem = SelectionMenuItem.node(
|
||||
name: LocaleKeys.document_plugins_toggleList.tr(),
|
||||
iconData: Icons.arrow_right,
|
||||
keywords: ['collapsed list', 'toggle list', 'list'],
|
||||
nodeBuilder: (editorState) => toggleListBlockNode(),
|
||||
replace: (_, node) => node.delta?.isEmpty ?? false,
|
||||
);
|
||||
|
||||
class ToggleListBlockComponentBuilder extends BlockComponentBuilder {
|
||||
ToggleListBlockComponentBuilder({
|
||||
this.configuration = const BlockComponentConfiguration(),
|
||||
|
@ -220,6 +220,12 @@ class EditorStyleCustomizer {
|
||||
);
|
||||
}
|
||||
|
||||
return textSpan;
|
||||
return defaultTextSpanDecoratorForAttribute(
|
||||
context,
|
||||
node,
|
||||
index,
|
||||
text,
|
||||
textSpan,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "33b18d9"
|
||||
resolved-ref: "33b18d98dcc6db996eef3d6b869f293da3da3615"
|
||||
ref: "023f3c8"
|
||||
resolved-ref: "023f3c835dc427a932bb2022a0d213c0084ffb99"
|
||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||
source: git
|
||||
version: "1.2.0"
|
||||
@ -1002,7 +1002,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
|
||||
@ -1567,7 +1567,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370"
|
||||
|
@ -115,6 +115,9 @@ dev_dependencies:
|
||||
json_serializable: ^6.7.0
|
||||
envied_generator: ^0.3.0+3
|
||||
|
||||
plugin_platform_interface: any
|
||||
url_launcher_platform_interface: any
|
||||
|
||||
dependency_overrides:
|
||||
http: ^1.0.0
|
||||
|
||||
|
@ -453,6 +453,7 @@
|
||||
"smartEditDisabled": "Connect OpenAI in Settings",
|
||||
"discardResponse": "Do you want to discard the AI responses?",
|
||||
"createInlineMathEquation": "Create equation",
|
||||
"toggleList": "Toggle List",
|
||||
"cover": {
|
||||
"changeCover": "Change Cover",
|
||||
"colors": "Colors",
|
||||
|
Loading…
Reference in New Issue
Block a user