fix: command shortcuts on the web platform should also respect the operating system

This commit is contained in:
Lucas.Xu 2023-09-24 10:51:42 +08:00
commit c9adbb1714
6 changed files with 71 additions and 166 deletions

View file

@ -1,7 +1,4 @@
import 'dart:io';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
typedef CommandShortcutEventHandler = KeyEventResult Function(
@ -67,23 +64,17 @@ class CommandShortcutEvent {
return;
}
var matched = false;
if (kIsWeb) {
// We shouldn't continue to run the below `else if` code in Web platform, it will throw an `_operatingSystem` exception.
if (command != null && command.isNotEmpty) {
this.command = command;
matched = true;
}
} else if (Platform.isWindows &&
if ((PlatformExtension.isWindows || PlatformExtension.isWebOnWindows) &&
windowsCommand != null &&
windowsCommand.isNotEmpty) {
this.command = windowsCommand;
matched = true;
} else if (Platform.isMacOS &&
} else if ((PlatformExtension.isMacOS || PlatformExtension.isWebOnMacOS) &&
macOSCommand != null &&
macOSCommand.isNotEmpty) {
this.command = macOSCommand;
matched = true;
} else if (Platform.isLinux &&
} else if ((PlatformExtension.isLinux || PlatformExtension.isWebOnLinux) &&
linuxCommand != null &&
linuxCommand.isNotEmpty) {
this.command = linuxCommand;

View file

@ -1,9 +1,14 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:universal_html/html.dart' show window;
// TODO(Xazin): Refactor to honor `Theme.platform`
extension PlatformExtension on Platform {
static String get _webPlatform =>
window.navigator.platform?.toLowerCase() ?? '';
/// Returns true if the operating system is macOS and not running on Web platform.
static bool get isMacOS {
if (kIsWeb) {
return false;
@ -11,6 +16,7 @@ extension PlatformExtension on Platform {
return Platform.isMacOS;
}
/// Returns true if the operating system is Windows and not running on Web platform.
static bool get isWindows {
if (kIsWeb) {
return false;
@ -18,6 +24,38 @@ extension PlatformExtension on Platform {
return Platform.isWindows;
}
/// Returns true if the operating system is Linux and not running on Web platform.
static bool get isLinux {
if (kIsWeb) {
return false;
}
return Platform.isLinux;
}
/// Returns true if the operating system is macOS and running on Web platform.
static bool get isWebOnMacOS {
if (!kIsWeb) {
return false;
}
return _webPlatform.contains('mac') == true;
}
/// Returns true if the operating system is Windows and running on Web platform.
static bool get isWebOnWindows {
if (!kIsWeb) {
return false;
}
return _webPlatform.contains('windows') == true;
}
/// Returns true if the operating system is Linux and running on Web platform.
static bool get isWebOnLinux {
if (!kIsWeb) {
return false;
}
return _webPlatform.contains('linux') == true;
}
static bool get isDesktopOrWeb {
if (kIsWeb) {
return true;

View file

@ -1,150 +0,0 @@
import 'dart:io';
import 'package:appflowy_editor/src/service/shortcut_event/keybinding.dart';
import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event_handler.dart';
import 'package:flutter/foundation.dart';
/// Defines the implementation of shortcut event.
class ShortcutEvent {
ShortcutEvent({
required this.key,
this.character,
this.command,
required this.handler,
String? windowsCommand,
String? macOSCommand,
String? linuxCommand,
}) {
// character and command cannot be null at the same time
assert(
!(character == null &&
command == null &&
windowsCommand == null &&
macOSCommand == null &&
linuxCommand == null),
'character and command cannot be null at the same time',
);
assert(
!(character != null &&
(command != null &&
windowsCommand != null &&
macOSCommand != null &&
linuxCommand != null)),
'character and command cannot be set at the same time',
);
updateCommand(
command: command,
windowsCommand: windowsCommand,
macOSCommand: macOSCommand,
linuxCommand: linuxCommand,
);
}
/// The unique key.
///
/// Usually, uses the description as the key.
final String key;
/// The string representation for the keyboard keys.
///
/// The following is the mapping relationship of modify key.
/// ctrl: Ctrl
/// meta: Command in macOS or Control in Windows.
/// alt: Alt
/// shift: Shift
/// cmd: meta
/// win: meta
///
/// Refer to [keyMapping] for other keys.
///
/// Uses ',' to split different keyboard key combinations.
///
/// Like, 'ctrl+c,cmd+c'
///
String? command;
String? character;
final ShortcutEventHandler handler;
List<Keybinding> get keybindings => _keybindings;
List<Keybinding> _keybindings = [];
void updateCommand({
String? command,
String? windowsCommand,
String? macOSCommand,
String? linuxCommand,
}) {
if (command == null &&
windowsCommand == null &&
macOSCommand == null &&
linuxCommand == null) {
return;
}
var matched = false;
if (kIsWeb) {
// We shouldn't continue to run the below `else if` code in Web platform, it will throw an `_operatingSystem` exception.
if (command != null && command.isNotEmpty) {
this.command = command;
matched = true;
}
} else if (Platform.isWindows &&
windowsCommand != null &&
windowsCommand.isNotEmpty) {
this.command = windowsCommand;
matched = true;
} else if (Platform.isMacOS &&
macOSCommand != null &&
macOSCommand.isNotEmpty) {
this.command = macOSCommand;
matched = true;
} else if (Platform.isLinux &&
linuxCommand != null &&
linuxCommand.isNotEmpty) {
this.command = linuxCommand;
matched = true;
} else if (command != null && command.isNotEmpty) {
this.command = command;
matched = true;
}
if (matched && this.command != null) {
_keybindings = this
.command!
.split(',')
.map((e) => Keybinding.parse(e))
.toList(growable: false);
}
}
ShortcutEvent copyWith({
String? key,
String? command,
ShortcutEventHandler? handler,
}) {
return ShortcutEvent(
key: key ?? this.key,
command: command ?? this.command,
handler: handler ?? this.handler,
);
}
@override
String toString() =>
'ShortcutEvent(key: $key, command: $command, handler: $handler)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ShortcutEvent &&
other.key == key &&
other.command == command &&
other.handler == handler;
}
@override
int get hashCode => key.hashCode ^ command.hashCode ^ handler.hashCode;
}

View file

@ -38,6 +38,7 @@ dependencies:
path: ^1.8.3
diff_match_patch: ^0.4.1
string_validator: ^1.0.0
universal_html: ^2.2.4
dev_dependencies:
flutter_test:

View file

@ -0,0 +1,26 @@
import 'dart:io';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('platform extension', () {
test('test safe platform judgement', () {
if (!kIsWeb && Platform.isLinux) {
expect(PlatformExtension.isLinux, true);
expect(PlatformExtension.isWebOnLinux, false);
}
if (!kIsWeb && Platform.isWindows) {
expect(PlatformExtension.isWindows, true);
expect(PlatformExtension.isWebOnWindows, false);
}
if (!kIsWeb && Platform.isMacOS) {
expect(PlatformExtension.isMacOS, true);
expect(PlatformExtension.isWebOnMacOS, false);
}
});
});
}

View file

@ -1,10 +1,9 @@
import 'dart:io';
import 'package:appflowy_editor/src/service/shortcut_event/shortcut_event.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:appflowy_editor/appflowy_editor.dart';
import '../../new/infra/testable_editor.dart';
@ -15,10 +14,10 @@ void main() async {
group('shortcut_event.dart', () {
test('redefine shortcut event command', () {
final shortcutEvent = ShortcutEvent(
final shortcutEvent = CommandShortcutEvent(
key: 'Sample',
command: 'cmd+shift+alt+ctrl+a',
handler: (editorState, event) {
handler: (editorState) {
return KeyEventResult.handled;
},
);