From b160adc654144561db9881d0673e1d1fd0e531c8 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Sat, 9 Oct 2021 13:37:08 +0800 Subject: [PATCH 01/16] feat: use 'scheme' instead of 'solution'. --- app/lib/models/local_schemes.dart | 21 +++++++ ...lutions_linux.dart => local_schemes_linux.dart} | 36 ++++++------ app/lib/models/local_schemes_provider.dart | 1 + app/lib/models/local_schemes_web.dart | 67 ++++++++++++++++++++++ app/lib/models/local_solutions.dart | 21 ------- app/lib/models/local_solutions_provider.dart | 1 - app/lib/models/local_solutions_web.dart | 67 ---------------------- app/lib/models/{solution.dart => scheme.dart} | 14 ++--- app/lib/pages/gesture_editor.dart | 8 +-- app/lib/pages/home.dart | 8 +-- app/lib/pages/local_manager.dart | 12 ++-- app/lib/utils/helper.dart | 2 +- app/resources/langs/en.json | 6 +- 13 files changed, 132 insertions(+), 132 deletions(-) create mode 100644 app/lib/models/local_schemes.dart rename app/lib/models/{local_solutions_linux.dart => local_schemes_linux.dart} (51%) create mode 100644 app/lib/models/local_schemes_provider.dart create mode 100644 app/lib/models/local_schemes_web.dart delete mode 100644 app/lib/models/local_solutions.dart delete mode 100644 app/lib/models/local_solutions_provider.dart delete mode 100644 app/lib/models/local_solutions_web.dart rename app/lib/models/{solution.dart => scheme.dart} (83%) diff --git a/app/lib/models/local_schemes.dart b/app/lib/models/local_schemes.dart new file mode 100644 index 0000000..d092b43 --- /dev/null +++ b/app/lib/models/local_schemes.dart @@ -0,0 +1,21 @@ +export 'local_schemes_web.dart' if (dart.library.io) 'local_schemes_linux.dart'; + +import 'package:dde_gesture_manager/models/scheme.dart'; + +abstract class LocalSchemeEntry { + Scheme scheme; + DateTime lastModifyTime; + String path; + + LocalSchemeEntry({ + required this.path, + required this.scheme, + required this.lastModifyTime, + }); + + save(); +} + +abstract class LocalSchemesInterface { + Future> get schemeEntries; +} \ No newline at end of file diff --git a/app/lib/models/local_solutions_linux.dart b/app/lib/models/local_schemes_linux.dart similarity index 51% rename from app/lib/models/local_solutions_linux.dart rename to app/lib/models/local_schemes_linux.dart index 80cc63e..9979895 100644 --- a/app/lib/models/local_solutions_linux.dart +++ b/app/lib/models/local_schemes_linux.dart @@ -2,61 +2,61 @@ import 'dart:io'; import 'package:dde_gesture_manager/builder/provider_annotation.dart'; import 'package:dde_gesture_manager/extensions.dart'; -import 'package:dde_gesture_manager/models/solution.dart'; +import 'package:dde_gesture_manager/models/scheme.dart'; import 'package:path/path.dart' show join; import 'package:path_provider/path_provider.dart'; -import 'local_solutions.dart'; +import 'local_schemes.dart'; -export 'local_solutions.dart'; +export 'local_schemes.dart'; @ProviderModel() -class LocalSolutions implements LocalSolutionsInterface { - LocalSolutions() { - solutionEntries.then((value) => solutions = value); +class LocalSchemes implements LocalSchemesInterface { + LocalSchemes() { + schemeEntries.then((value) => schemes = value); } @override - Future> get solutionEntries async { + Future> get schemeEntries async { var _supportDirectory = await getApplicationSupportDirectory(); - var directory = Directory(join(_supportDirectory.path, 'solutions')); + var directory = Directory(join(_supportDirectory.path, 'schemes')); if (!directory.existsSync()) directory.createSync(); directory.path.sout(); return directory .list() - .map((f) { - LocalSolutionEntryLinux? entry; + .map((f) { + LocalSchemeEntryLinux? entry; try { var content = File(f.path).readAsStringSync(); - entry = LocalSolutionEntryLinux( - path: f.path, solution: Solution.parse(content), lastModifyTime: f.statSync().modified); + entry = LocalSchemeEntryLinux( + path: f.path, scheme: Scheme.parse(content), lastModifyTime: f.statSync().modified); } catch (e) { e.sout(); } return entry; }) .where((e) => e != null) - .cast() + .cast() .toList(); } @ProviderModelProp() - List? solutions; + List? schemes; } -class LocalSolutionEntryLinux implements LocalSolutionEntry { +class LocalSchemeEntryLinux implements LocalSchemeEntry { @override String path; @override - Solution solution; + Scheme scheme; @override DateTime lastModifyTime; - LocalSolutionEntryLinux({ + LocalSchemeEntryLinux({ required this.path, - required this.solution, + required this.scheme, required this.lastModifyTime, }); diff --git a/app/lib/models/local_schemes_provider.dart b/app/lib/models/local_schemes_provider.dart new file mode 100644 index 0000000..3e23c89 --- /dev/null +++ b/app/lib/models/local_schemes_provider.dart @@ -0,0 +1 @@ +export 'local_schemes_web.provider.dart' if (dart.library.io) 'local_schemes_linux.provider.dart'; \ No newline at end of file diff --git a/app/lib/models/local_schemes_web.dart b/app/lib/models/local_schemes_web.dart new file mode 100644 index 0000000..51c08e0 --- /dev/null +++ b/app/lib/models/local_schemes_web.dart @@ -0,0 +1,67 @@ +import 'dart:convert'; + +import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +import 'package:dde_gesture_manager/models/scheme.dart'; +import 'package:dde_gesture_manager/extensions.dart'; +import 'dart:html'; + +import 'local_schemes.dart'; +export 'local_schemes.dart'; + +@ProviderModel() +class LocalSchemes implements LocalSchemesInterface { + LocalSchemes() { + schemeEntries.then((value) => schemes = value); + } + + @override + Future> get schemeEntries async { + return window.localStorage.keys + .map((key) { + if (key.startsWith('schemes.')) { + LocalSchemeEntryWeb? entry; + try { + var content = window.localStorage[key] ?? ''; + var schemeJson = json.decode(content); + entry = LocalSchemeEntryWeb( + path: key, + scheme: Scheme.parse(schemeJson), + lastModifyTime: DateTime.parse(schemeJson['modified_at']), + ); + } catch (e) { + e.sout(); + } + return entry; + } + }) + .where((e) => e != null) + .cast() + .toList(); + } + + @ProviderModelProp() + List? schemes; +} + +class LocalSchemeEntryWeb implements LocalSchemeEntry { + @override + String path; + + @override + Scheme scheme; + + @override + DateTime lastModifyTime; + + LocalSchemeEntryWeb({ + required this.path, + required this.scheme, + required this.lastModifyTime, + }); + + @override + save() { + // TODO: implement save + throw UnimplementedError(); + } +} diff --git a/app/lib/models/local_solutions.dart b/app/lib/models/local_solutions.dart deleted file mode 100644 index e2249ed..0000000 --- a/app/lib/models/local_solutions.dart +++ /dev/null @@ -1,21 +0,0 @@ -export 'local_solutions_web.dart' if (dart.library.io) 'local_solutions_linux.dart'; - -import 'package:dde_gesture_manager/models/solution.dart'; - -abstract class LocalSolutionEntry { - Solution solution; - DateTime lastModifyTime; - String path; - - LocalSolutionEntry({ - required this.path, - required this.solution, - required this.lastModifyTime, - }); - - save(); -} - -abstract class LocalSolutionsInterface { - Future> get solutionEntries; -} \ No newline at end of file diff --git a/app/lib/models/local_solutions_provider.dart b/app/lib/models/local_solutions_provider.dart deleted file mode 100644 index 6a10556..0000000 --- a/app/lib/models/local_solutions_provider.dart +++ /dev/null @@ -1 +0,0 @@ -export 'local_solutions_web.provider.dart' if (dart.library.io) 'local_solutions_linux.provider.dart'; \ No newline at end of file diff --git a/app/lib/models/local_solutions_web.dart b/app/lib/models/local_solutions_web.dart deleted file mode 100644 index 81faed7..0000000 --- a/app/lib/models/local_solutions_web.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'dart:convert'; - -import 'package:dde_gesture_manager/builder/provider_annotation.dart'; -import 'package:dde_gesture_manager/models/solution.dart'; -import 'package:dde_gesture_manager/extensions.dart'; -import 'dart:html'; - -import 'local_solutions.dart'; -export 'local_solutions.dart'; - -@ProviderModel() -class LocalSolutions implements LocalSolutionsInterface { - LocalSolutions() { - solutionEntries.then((value) => solutions = value); - } - - @override - Future> get solutionEntries async { - return window.localStorage.keys - .map((key) { - if (key.startsWith('solutions.')) { - LocalSolutionEntryWeb? entry; - try { - var content = window.localStorage[key] ?? ''; - var solutionJson = json.decode(content); - entry = LocalSolutionEntryWeb( - path: key, - solution: Solution.parse(solutionJson), - lastModifyTime: DateTime.parse(solutionJson['modified_at']), - ); - } catch (e) { - e.sout(); - } - return entry; - } - }) - .where((e) => e != null) - .cast() - .toList(); - } - - @ProviderModelProp() - List? solutions; -} - -class LocalSolutionEntryWeb implements LocalSolutionEntry { - @override - String path; - - @override - Solution solution; - - @override - DateTime lastModifyTime; - - LocalSolutionEntryWeb({ - required this.path, - required this.solution, - required this.lastModifyTime, - }); - - @override - save() { - // TODO: implement save - throw UnimplementedError(); - } -} diff --git a/app/lib/models/solution.dart b/app/lib/models/scheme.dart similarity index 83% rename from app/lib/models/solution.dart rename to app/lib/models/scheme.dart index 14583ed..5248303 100644 --- a/app/lib/models/solution.dart +++ b/app/lib/models/scheme.dart @@ -4,7 +4,7 @@ import 'package:dde_gesture_manager/builder/provider_annotation.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; @ProviderModel(copyable: true) -class Solution { +class Scheme { @ProviderModelProp() String? name; @@ -14,12 +14,12 @@ class Solution { @ProviderModelProp() List? gestures; - Solution.parse(solution) { - if (solution is String) solution = json.decode(solution); - assert(solution is Map); - name = solution['name']; - description = solution['desc']; - gestures = (solution['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList(); + Scheme.parse(scheme) { + if (scheme is String) scheme = json.decode(scheme); + assert(scheme is Map); + name = scheme['name']; + description = scheme['desc']; + gestures = (scheme['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList(); } } diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 566ffe5..c94826d 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -1,8 +1,8 @@ import 'package:dde_gesture_manager/constants/constants.dart'; import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/content_layout.provider.dart'; -import 'package:dde_gesture_manager/models/solution.dart'; -import 'package:dde_gesture_manager/models/solution.provider.dart'; +import 'package:dde_gesture_manager/models/scheme.dart'; +import 'package:dde_gesture_manager/models/scheme.provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; @@ -50,7 +50,7 @@ class GestureEditor extends StatelessWidget { @override Widget build(BuildContext context) { var layoutProvider = context.watch(); - var solutionProvider = context.watch(); + var schemeProvider = context.watch(); return Flexible( child: Padding( padding: const EdgeInsets.all(10), @@ -140,7 +140,7 @@ class GestureEditor extends StatelessWidget { DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), ], - rows: _buildDataRow(solutionProvider.gestures, context), + rows: _buildDataRow(schemeProvider.gestures, context), ), ), ), diff --git a/app/lib/pages/home.dart b/app/lib/pages/home.dart index 26341bc..50d1f8c 100644 --- a/app/lib/pages/home.dart +++ b/app/lib/pages/home.dart @@ -1,6 +1,6 @@ import 'package:dde_gesture_manager/extensions.dart'; -import 'package:dde_gesture_manager/models/local_solutions_provider.dart'; -import 'package:dde_gesture_manager/models/solution.provider.dart'; +import 'package:dde_gesture_manager/models/local_schemes_provider.dart'; +import 'package:dde_gesture_manager/models/scheme.provider.dart'; import 'package:dde_gesture_manager/pages/content.dart'; import 'package:dde_gesture_manager/pages/footer.dart'; import 'package:flutter/material.dart'; @@ -18,7 +18,7 @@ class _HomePageState extends State { return Scaffold( body: MultiProvider( providers: [ - ChangeNotifierProvider(create: (context) => SolutionProvider.parse(''' + ChangeNotifierProvider(create: (context) => SchemeProvider.parse(''' { "name": "test", "desc": "some desc", @@ -66,7 +66,7 @@ class _HomePageState extends State { } ''')), ChangeNotifierProvider(create: (context) => GesturePropProvider.empty()), - ChangeNotifierProvider(create: (context) => LocalSolutionsProvider(),lazy: false), + ChangeNotifierProvider(create: (context) => LocalSchemesProvider(),lazy: false), ], child: Column( mainAxisSize: MainAxisSize.max, diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index 7fcab24..51daa65 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -1,8 +1,8 @@ import 'package:dde_gesture_manager/constants/constants.dart'; import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/content_layout.provider.dart'; -import 'package:dde_gesture_manager/models/local_solutions_provider.dart'; -import 'package:dde_gesture_manager/models/solution.provider.dart'; +import 'package:dde_gesture_manager/models/local_schemes_provider.dart'; +import 'package:dde_gesture_manager/models/scheme.provider.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/cupertino.dart'; @@ -39,7 +39,7 @@ class _LocalManagerState extends State { @override Widget build(BuildContext context) { var isOpen = context.watch().localManagerOpened == true; - var localSolutions = context.watch().solutions ?? []; + var localschemes = context.watch().schemes ?? []; return AnimatedContainer( duration: mediumDuration, curve: Curves.easeInOut, @@ -91,7 +91,7 @@ class _LocalManagerState extends State { controller: _scrollController, itemBuilder: (context, index) => GestureDetector( onDoubleTap: () { - context.read().copyFrom(localSolutions[index].solution); + context.read().copyFrom(localschemes[index].scheme); setState(() { _selectedIndex = index; }); @@ -115,7 +115,7 @@ class _LocalManagerState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(localSolutions[index].solution.name ?? ''), + Text(localschemes[index].scheme.name ?? ''), Text('456'), ], ), @@ -123,7 +123,7 @@ class _LocalManagerState extends State { ), ), ), - itemCount: localSolutions.length, + itemCount: localschemes.length, ), ), Container( diff --git a/app/lib/utils/helper.dart b/app/lib/utils/helper.dart index c510eac..c71ba0c 100644 --- a/app/lib/utils/helper.dart +++ b/app/lib/utils/helper.dart @@ -1,5 +1,5 @@ import 'package:dde_gesture_manager/models/content_layout.provider.dart'; -import 'package:dde_gesture_manager/models/solution.dart'; +import 'package:dde_gesture_manager/models/scheme.dart'; import 'package:flutter/cupertino.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:dde_gesture_manager/constants/constants.dart'; diff --git a/app/resources/langs/en.json b/app/resources/langs/en.json index f687fa5..4538c75 100644 --- a/app/resources/langs/en.json +++ b/app/resources/langs/en.json @@ -20,13 +20,13 @@ "tip": "Display help documentation" }, "market": { - "title": "Solution market" + "title": "Scheme market" }, "local_manager": { - "title": "Local solution management" + "title": "Local scheme management" }, "gesture_editor": { - "label": "Gesture program editing", + "label": "Gesture scheme editing", "gesture": "gesture", "direction": "direction", "fingers": "fingers", From d3a69573c395b0e1b0006f22f1ec506c4b72a76b Mon Sep 17 00:00:00 2001 From: debuggerx Date: Sat, 9 Oct 2021 18:42:12 +0800 Subject: [PATCH 02/16] feat: add default scheme to local manager. --- app/lib/models/local_schemes.dart | 11 +++++++++-- app/lib/models/local_schemes_linux.dart | 9 ++++++++- app/lib/models/local_schemes_web.dart | 14 +++++++++++--- app/lib/models/scheme.dart | 7 +++++++ app/lib/pages/local_manager.dart | 8 ++++---- app/resources/langs/en.json | 6 +++++- app/resources/langs/zh-CN.json | 6 +++++- 7 files changed, 49 insertions(+), 12 deletions(-) diff --git a/app/lib/models/local_schemes.dart b/app/lib/models/local_schemes.dart index d092b43..8d841df 100644 --- a/app/lib/models/local_schemes.dart +++ b/app/lib/models/local_schemes.dart @@ -1,7 +1,7 @@ -export 'local_schemes_web.dart' if (dart.library.io) 'local_schemes_linux.dart'; - import 'package:dde_gesture_manager/models/scheme.dart'; +export 'local_schemes_web.dart' if (dart.library.io) 'local_schemes_linux.dart'; + abstract class LocalSchemeEntry { Scheme scheme; DateTime lastModifyTime; @@ -13,6 +13,13 @@ abstract class LocalSchemeEntry { required this.lastModifyTime, }); + LocalSchemeEntry.systemDefault() + : this.path = '', + this.scheme = Scheme.systemDefault(), + + /// max value of DateTime ![Time Values and Time Range](https://262.ecma-international.org/11.0/#sec-time-values-and-time-range) + this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000); + save(); } diff --git a/app/lib/models/local_schemes_linux.dart b/app/lib/models/local_schemes_linux.dart index 9979895..e1fc413 100644 --- a/app/lib/models/local_schemes_linux.dart +++ b/app/lib/models/local_schemes_linux.dart @@ -13,7 +13,7 @@ export 'local_schemes.dart'; @ProviderModel() class LocalSchemes implements LocalSchemesInterface { LocalSchemes() { - schemeEntries.then((value) => schemes = value); + schemeEntries.then((value) => schemes = [LocalSchemeEntryLinux.systemDefault(), ...value]); } @override @@ -60,6 +60,13 @@ class LocalSchemeEntryLinux implements LocalSchemeEntry { required this.lastModifyTime, }); + LocalSchemeEntryLinux.systemDefault() + : this.path = '', + this.scheme = Scheme.systemDefault(), + + /// max value of DateTime ![Time Values and Time Range](https://262.ecma-international.org/11.0/#sec-time-values-and-time-range) + this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000); + @override save() { // TODO: implement save diff --git a/app/lib/models/local_schemes_web.dart b/app/lib/models/local_schemes_web.dart index 51c08e0..c8c1814 100644 --- a/app/lib/models/local_schemes_web.dart +++ b/app/lib/models/local_schemes_web.dart @@ -1,17 +1,18 @@ import 'dart:convert'; +import 'dart:html'; import 'package:dde_gesture_manager/builder/provider_annotation.dart'; -import 'package:dde_gesture_manager/models/scheme.dart'; import 'package:dde_gesture_manager/extensions.dart'; -import 'dart:html'; +import 'package:dde_gesture_manager/models/scheme.dart'; import 'local_schemes.dart'; + export 'local_schemes.dart'; @ProviderModel() class LocalSchemes implements LocalSchemesInterface { LocalSchemes() { - schemeEntries.then((value) => schemes = value); + schemeEntries.then((value) => schemes = [LocalSchemeEntryWeb.systemDefault(), ...value]); } @override @@ -59,6 +60,13 @@ class LocalSchemeEntryWeb implements LocalSchemeEntry { required this.lastModifyTime, }); + LocalSchemeEntryWeb.systemDefault() + : this.path = '', + this.scheme = Scheme.systemDefault(), + + /// max value of DateTime ![Time Values and Time Range](https://262.ecma-international.org/11.0/#sec-time-values-and-time-range) + this.lastModifyTime = DateTime.fromMillisecondsSinceEpoch(8640000000000000); + @override save() { // TODO: implement save diff --git a/app/lib/models/scheme.dart b/app/lib/models/scheme.dart index 5248303..2f4608c 100644 --- a/app/lib/models/scheme.dart +++ b/app/lib/models/scheme.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; @ProviderModel(copyable: true) @@ -21,6 +22,12 @@ class Scheme { description = scheme['desc']; gestures = (scheme['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList(); } + + Scheme.systemDefault() { + this.name = LocaleKeys.local_manager_default_scheme_label.tr(); + this.description = LocaleKeys.local_manager_default_scheme_description.tr(); + this.gestures = []; + } } enum Gesture { diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index 51daa65..037a032 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -39,7 +39,7 @@ class _LocalManagerState extends State { @override Widget build(BuildContext context) { var isOpen = context.watch().localManagerOpened == true; - var localschemes = context.watch().schemes ?? []; + var localSchemes = context.watch().schemes ?? []; return AnimatedContainer( duration: mediumDuration, curve: Curves.easeInOut, @@ -91,7 +91,7 @@ class _LocalManagerState extends State { controller: _scrollController, itemBuilder: (context, index) => GestureDetector( onDoubleTap: () { - context.read().copyFrom(localschemes[index].scheme); + context.read().copyFrom(localSchemes[index].scheme); setState(() { _selectedIndex = index; }); @@ -115,7 +115,7 @@ class _LocalManagerState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(localschemes[index].scheme.name ?? ''), + Text(localSchemes[index].scheme.name ?? ''), Text('456'), ], ), @@ -123,7 +123,7 @@ class _LocalManagerState extends State { ), ), ), - itemCount: localschemes.length, + itemCount: localSchemes.length, ), ), Container( diff --git a/app/resources/langs/en.json b/app/resources/langs/en.json index 4538c75..7c1a22a 100644 --- a/app/resources/langs/en.json +++ b/app/resources/langs/en.json @@ -23,7 +23,11 @@ "title": "Scheme market" }, "local_manager": { - "title": "Local scheme management" + "title": "Local scheme management", + "default_scheme": { + "label": "System default scheme", + "description": "System default gesture scheme, cannot be modified. (Secretly telling you that there is no actual content in this scheme, just when applying the scheme, it is achieved by deleting a custom configuration scheme." + } }, "gesture_editor": { "label": "Gesture scheme editing", diff --git a/app/resources/langs/zh-CN.json b/app/resources/langs/zh-CN.json index ff97b4d..12c8ed0 100644 --- a/app/resources/langs/zh-CN.json +++ b/app/resources/langs/zh-CN.json @@ -23,7 +23,11 @@ "title": "方案市场" }, "local_manager": { - "title": "本地方案管理" + "title": "本地方案管理", + "default_scheme": { + "label": "系统默认方案", + "description": "系统默认的手势方案,不可修改。(偷偷告诉你,这个这个方案里没有任何实际内容,应用该方案时不过是通过删除自定义配置方案的方式来实现恢复系统默认方案~)" + } }, "gesture_editor": { "label": "手势方案编辑", From 8fa6c51ea2478c0fea81983d523688b6f1dd64c0 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Sun, 10 Oct 2021 02:20:04 +0800 Subject: [PATCH 03/16] fix: issues when change language. --- app/lib/widgets/language_switcher.dart | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/lib/widgets/language_switcher.dart b/app/lib/widgets/language_switcher.dart index 50c7df1..d82bec7 100644 --- a/app/lib/widgets/language_switcher.dart +++ b/app/lib/widgets/language_switcher.dart @@ -2,12 +2,15 @@ import 'package:collection/collection.dart'; import 'package:dde_gesture_manager/constants/sp_keys.dart'; import 'package:dde_gesture_manager/constants/supported_locales.dart'; import 'package:dde_gesture_manager/extensions.dart'; +import 'package:dde_gesture_manager/generated/codegen_loader.g.dart'; import 'package:dde_gesture_manager/generated/locale_keys.g.dart'; +import 'package:dde_gesture_manager/models/local_schemes_provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; +import 'package:easy_localization/src/translations.dart'; class LanguageSwitcher extends StatelessWidget { const LanguageSwitcher({Key? key}) : super(key: key); @@ -18,7 +21,7 @@ class LanguageSwitcher extends StatelessWidget { var _supportedLocale = supportedLocales.firstWhereOrNull((element) => element == _locale); return PopupMenuButton( - tooltip: LocaleKeys.language_tip.tr(), + tooltip: LocaleKeys.language_tip.tr(), child: Row( children: [ Icon(Icons.language_outlined, size: 20), @@ -41,7 +44,18 @@ class LanguageSwitcher extends StatelessWidget { ), onTap: () { EasyLocalization.of(context)?.setLocale(locale).then((_) { - if (!kIsWeb) WindowManager.instance.setTitle(LocaleKeys.app_name.tr()); + context.locale.sout(); + var localeMap = Translations(CodegenLoader.mapLocales[context.locale.toString()]!); + if (!kIsWeb) WindowManager.instance.setTitle(localeMap.get(LocaleKeys.app_name)!); + var localSchemesProvider = context.read(); + var schemes = localSchemesProvider.schemes!; + var newSchemes = [ + schemes.first + ..scheme.name = localeMap.get(LocaleKeys.local_manager_default_scheme_label) + ..scheme.description = localeMap.get(LocaleKeys.local_manager_default_scheme_description), + ...schemes.skip(1), + ]; + localSchemesProvider.setProps(schemes: newSchemes); }); H().sp.setInt(SPKeys.userLanguage, supportedLocales.indexOf(locale)); }, From f58e76ba259b9757650bd574080adf9b4c61e6fc Mon Sep 17 00:00:00 2001 From: debuggerx Date: Sun, 10 Oct 2021 02:30:37 +0800 Subject: [PATCH 04/16] fix: a render flex overflowed warning from dde data table. --- app/lib/models/local_schemes_linux.dart | 1 - app/lib/widgets/dde_data_table.dart | 2 +- app/lib/widgets/language_switcher.dart | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/lib/models/local_schemes_linux.dart b/app/lib/models/local_schemes_linux.dart index e1fc413..105dd79 100644 --- a/app/lib/models/local_schemes_linux.dart +++ b/app/lib/models/local_schemes_linux.dart @@ -21,7 +21,6 @@ class LocalSchemes implements LocalSchemesInterface { var _supportDirectory = await getApplicationSupportDirectory(); var directory = Directory(join(_supportDirectory.path, 'schemes')); if (!directory.existsSync()) directory.createSync(); - directory.path.sout(); return directory .list() .map((f) { diff --git a/app/lib/widgets/dde_data_table.dart b/app/lib/widgets/dde_data_table.dart index b1ebe2b..2e032ee 100644 --- a/app/lib/widgets/dde_data_table.dart +++ b/app/lib/widgets/dde_data_table.dart @@ -755,7 +755,7 @@ class _DDataTableState extends State { textDirection: numeric ? TextDirection.rtl : null, mainAxisAlignment: center ? MainAxisAlignment.spaceAround : MainAxisAlignment.start, children: [ - label, + Flexible(child: label), if (onSort != null) ...[ _SortArrow( visible: sorted, diff --git a/app/lib/widgets/language_switcher.dart b/app/lib/widgets/language_switcher.dart index d82bec7..16db130 100644 --- a/app/lib/widgets/language_switcher.dart +++ b/app/lib/widgets/language_switcher.dart @@ -44,7 +44,6 @@ class LanguageSwitcher extends StatelessWidget { ), onTap: () { EasyLocalization.of(context)?.setLocale(locale).then((_) { - context.locale.sout(); var localeMap = Translations(CodegenLoader.mapLocales[context.locale.toString()]!); if (!kIsWeb) WindowManager.instance.setTitle(localeMap.get(LocaleKeys.app_name)!); var localSchemesProvider = context.read(); From bf652afe6cec92f526862cf96471eed8c132fc69 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Tue, 12 Oct 2021 02:55:30 +0800 Subject: [PATCH 05/16] feat: add active color to settings provider. --- app/lib/models/settings.dart | 8 ++++ app/lib/pages/gesture_editor.dart | 99 ++++++++++++++++++++++++++------------- app/lib/pages/local_manager.dart | 17 +++++-- app/lib/utils/helper.dart | 11 ++++- app/lib/utils/init_linux.dart | 7 +++ 5 files changed, 105 insertions(+), 37 deletions(-) diff --git a/app/lib/models/settings.dart b/app/lib/models/settings.dart index 27a264d..844b0a4 100644 --- a/app/lib/models/settings.dart +++ b/app/lib/models/settings.dart @@ -1,7 +1,15 @@ import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +import 'package:flutter/material.dart'; + +export 'package:flutter/material.dart' show Color; @ProviderModel() class Settings { @ProviderModelProp() bool? isDarkMode; + + @ProviderModelProp() + Color? activeColor; + + Color get currentActiveColor => activeColor ?? const Color(0xff0069cc); } diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index c94826d..11545c5 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -3,6 +3,7 @@ import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/content_layout.provider.dart'; import 'package:dde_gesture_manager/models/scheme.dart'; import 'package:dde_gesture_manager/models/scheme.provider.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; @@ -12,40 +13,71 @@ import 'package:flutter/material.dart'; class GestureEditor extends StatelessWidget { const GestureEditor({Key? key}) : super(key: key); - List _buildDataRow(List? gestures, BuildContext context) => (gestures ?? []) - .map((gesture) => DDataRow( - onSelectChanged: (selected) { - if (selected == true) - context.read().setProps( - gesture: gesture.gesture, - direction: gesture.direction, - fingers: gesture.fingers, - type: gesture.type, - command: gesture.command, - remark: gesture.remark, - ); - }, - selected: context.watch() == gesture, - cells: [ - Center( - child: Text('${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}').tr(), + List _buildDataRow(List? gestures, BuildContext context) => (gestures ?? []).map((gesture) { + bool selected = context.watch() == gesture; + return DDataRow( + onSelectChanged: (selected) { + if (selected == true) + context.read().setProps( + gesture: gesture.gesture, + direction: gesture.direction, + fingers: gesture.fingers, + type: gesture.type, + command: gesture.command, + remark: gesture.remark, + ); + }, + selected: selected, + cells: [ + Center( + child: Text( + '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ).tr(), + ), + Center( + child: Text( + '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}', + style: TextStyle( + color: selected ? Colors.white : null, ), - Center( - child: Text('${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}') - .tr()), - Center( - child: Text('${gesture.fingers}'), + ).tr()), + Center( + child: Text( + '${gesture.fingers}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + ), + Center( + child: Text( + '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', + style: TextStyle( + color: selected ? Colors.white : null, ), - Center(child: Text('${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}').tr()), - Text(gesture.command ?? ''), - Text(gesture.remark ?? ''), - ] - .map( - (ele) => DDataCell(ele), - ) - .toList(), - )) - .toList(); + ).tr()), + Text( + gesture.command ?? '', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + Text( + gesture.remark ?? '', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + ] + .map( + (ele) => DDataCell(ele), + ) + .toList(), + ); + }).toList(); @override Widget build(BuildContext context) { @@ -129,7 +161,8 @@ class GestureEditor extends StatelessWidget { ), dataRowColor: MaterialStateProperty.resolveWith((Set states) { if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; - if (states.contains(MaterialState.selected)) return Colors.blueAccent; + if (states.contains(MaterialState.selected)) + return context.read().currentActiveColor; return null; }), columns: [ diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index 037a032..0f7b6e0 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -3,6 +3,7 @@ import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/content_layout.provider.dart'; import 'package:dde_gesture_manager/models/local_schemes_provider.dart'; import 'package:dde_gesture_manager/models/scheme.provider.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/cupertino.dart'; @@ -32,7 +33,7 @@ class _LocalManagerState extends State { Color _getItemBackgroundColor(int index) { Color _color = index % 2 == 0 ? context.t.scaffoldBackgroundColor : context.t.backgroundColor; if (index == _hoveringIndex) _color = context.t.scaffoldBackgroundColor; - if (index == _selectedIndex) _color = Colors.blueAccent; + if (index == _selectedIndex) _color = context.read().currentActiveColor; return _color; } @@ -115,8 +116,18 @@ class _LocalManagerState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(localSchemes[index].scheme.name ?? ''), - Text('456'), + Text( + localSchemes[index].scheme.name ?? '', + style: TextStyle( + color: index == _selectedIndex ? Colors.white : null, + ), + ), + Text( + '456', + style: TextStyle( + color: index == _selectedIndex ? Colors.white : null, + ), + ), ], ), ), diff --git a/app/lib/utils/helper.dart b/app/lib/utils/helper.dart index c71ba0c..2e274fc 100644 --- a/app/lib/utils/helper.dart +++ b/app/lib/utils/helper.dart @@ -96,7 +96,16 @@ class H { 'shortcut': GestureType.shortcut, 'commandline': GestureType.commandline, }[typeName] ?? - GestureType.built_in; + GestureType.built_in; + + static Color? parseQtActiveColor(String? inp) { + if (inp == null) return null; + var list = inp.split(','); + if (list.length != 4) return null; + var rgba = list.map((e) => int.parse(e) ~/ 257).toList(); + rgba.sout(); + return Color.fromARGB(rgba[3], rgba[0], rgba[1], rgba[2]); + } } class PreferredPanelsStatus { diff --git a/app/lib/utils/init_linux.dart b/app/lib/utils/init_linux.dart index ca8faa7..3544dfd 100644 --- a/app/lib/utils/init_linux.dart +++ b/app/lib/utils/init_linux.dart @@ -18,8 +18,11 @@ Future initEvents(BuildContext context) async { } else { var xsettings = GSettings('com.deepin.xsettings'); String? themeName; + Color? activeColor; try { themeName = (await xsettings.get('theme-name')).toString(); + var _activeColor = (await xsettings.get('qt-active-color')); + activeColor = H.parseQtActiveColor(_activeColor.toNative()); } catch (e) { print(e); context.read().setProps(isDarkMode: false); @@ -27,10 +30,14 @@ Future initEvents(BuildContext context) async { if (themeName != null) { context.read().setProps(isDarkMode: themeName.contains('dark')); + context.read().setProps(activeColor: activeColor); xsettings.keysChanged.listen((event) { xsettings.get('theme-name').then((value) { context.read().setProps(isDarkMode: value.toString().contains('dark')); }); + xsettings.get('qt-active-color').then((value) { + context.read().setProps(activeColor: H.parseQtActiveColor(value.toNative())); + }); }); } } From 12cdbaecbe15be2ca6cb1594e3adad6a58002b73 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Tue, 12 Oct 2021 14:18:59 +0800 Subject: [PATCH 06/16] feat: add operation buttons and tooltip background. --- app/lib/models/scheme.dart | 4 ++ app/lib/pages/local_manager.dart | 112 ++++++++++++++++++++++++--------------- app/lib/themes/dark.dart | 19 +++++-- app/lib/themes/light.dart | 11 ++++ app/lib/widgets/dde_button.dart | 69 ++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 47 deletions(-) diff --git a/app/lib/models/scheme.dart b/app/lib/models/scheme.dart index 2f4608c..22be9fb 100644 --- a/app/lib/models/scheme.dart +++ b/app/lib/models/scheme.dart @@ -7,6 +7,9 @@ import 'package:dde_gesture_manager/utils/helper.dart'; @ProviderModel(copyable: true) class Scheme { @ProviderModelProp() + String? id; + + @ProviderModelProp() String? name; @ProviderModelProp() @@ -18,6 +21,7 @@ class Scheme { Scheme.parse(scheme) { if (scheme is String) scheme = json.decode(scheme); assert(scheme is Map); + id = scheme['id']; name = scheme['name']; description = scheme['desc']; gestures = (scheme['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList(); diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index 037a032..8baf13c 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -21,11 +21,14 @@ class LocalManager extends StatefulWidget { class _LocalManagerState extends State { late ScrollController _scrollController; int? _hoveringIndex; - int? _selectedIndex; + late int _selectedIndex; @override void initState() { super.initState(); + + /// todo: load from sp + _selectedIndex = 0; _scrollController = ScrollController(); } @@ -83,54 +86,77 @@ class _LocalManagerState extends State { ], ), Flexible( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, index) => GestureDetector( - onDoubleTap: () { - context.read().copyFrom(localSchemes[index].scheme); - setState(() { - _selectedIndex = index; - }); - }, - onTap: () { - setState(() { - _selectedIndex = index; - }); - }, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (_) { - setState(() { - _hoveringIndex = index; - }); - }, - child: Container( - color: _getItemBackgroundColor(index), - child: Padding( - padding: const EdgeInsets.only(right: 12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(localSchemes[index].scheme.name ?? ''), - Text('456'), - ], + child: Padding( + padding: EdgeInsets.only(top: 5), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: .3, + color: context.t.dividerColor, + ), + borderRadius: BorderRadius.circular(defaultBorderRadius), + ), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 1, vertical: 2), + child: ListView.builder( + controller: _scrollController, + itemBuilder: (context, index) => GestureDetector( + onTap: () { + context.read().copyFrom(localSchemes[index].scheme); + setState(() { + _selectedIndex = index; + }); + }, + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) { + setState(() { + _hoveringIndex = index; + }); + }, + child: Container( + color: _getItemBackgroundColor(index), + child: Padding( + padding: const EdgeInsets.only(left: 6, right: 12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(localSchemes[index].scheme.name ?? ''), + Text('456'), + ], + ), + ), + ), ), ), + itemCount: localSchemes.length, ), ), ), - itemCount: localSchemes.length, ), - ), - Container( - height: 150, - color: Colors.black, - ), - ], + Container(height: 5), + Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + DButton.add(enabled: true), + DButton.delete(enabled: _selectedIndex > 0), + DButton.duplicate(enabled: _selectedIndex > 0), + DButton.apply(enabled: _selectedIndex > 0), + ] + .map((e) => Padding( + padding: const EdgeInsets.only(right: 4), + child: e, + )) + .toList(), + ), + ), + ], + ), ), ), ], diff --git a/app/lib/themes/dark.dart b/app/lib/themes/dark.dart index 5746339..1d3f280 100644 --- a/app/lib/themes/dark.dart +++ b/app/lib/themes/dark.dart @@ -18,9 +18,20 @@ var darkTheme = ThemeData.dark().copyWith( ), ), popupMenuTheme: ThemeData.dark().popupMenuTheme.copyWith( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(defaultBorderRadius), - ), - ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(defaultBorderRadius), + ), + ), dialogBackgroundColor: Color(0xff202020), + tooltipTheme: ThemeData.dark().tooltipTheme.copyWith( + textStyle: TextStyle( + color: Colors.grey, + ), + padding: EdgeInsets.symmetric(horizontal: 3, vertical: 2), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Color(0xff282828).withOpacity(.9), + border: Border.all(color: Colors.black38), + ), + ), ); diff --git a/app/lib/themes/light.dart b/app/lib/themes/light.dart index ffeee59..fc0b49c 100644 --- a/app/lib/themes/light.dart +++ b/app/lib/themes/light.dart @@ -23,4 +23,15 @@ var lightTheme = ThemeData.light().copyWith( ), ), dialogBackgroundColor: Color(0xfffefefe), + tooltipTheme: ThemeData.dark().tooltipTheme.copyWith( + textStyle: TextStyle( + color: Colors.grey.shade600, + ), + padding: EdgeInsets.symmetric(horizontal: 3, vertical: 2), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: Color(0xfff8f8f8).withOpacity(.9), + border: Border.all(color: Colors.grey.shade400), + ), + ), ); diff --git a/app/lib/widgets/dde_button.dart b/app/lib/widgets/dde_button.dart index 70b87b9..faabfc4 100644 --- a/app/lib/widgets/dde_button.dart +++ b/app/lib/widgets/dde_button.dart @@ -1,4 +1,5 @@ import 'package:dde_gesture_manager/constants/constants.dart'; +import 'package:dde_gesture_manager/extensions.dart'; import 'package:flutter/material.dart'; import 'package:glass_kit/glass_kit.dart'; @@ -16,6 +17,74 @@ class DButton extends StatefulWidget { this.onTap, }) : super(key: key); + factory DButton.add({ + Key? key, + required enabled, + GestureTapCallback? onTap, + height = defaultButtonHeight * .7, + width = defaultButtonHeight * .7, + }) => + DButton( + key: key, + width: width, + height: height, + onTap: onTap, + child: Tooltip( + child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.add, size: 18)), + message: LocaleKeys.operation_add.tr(), + )); + + factory DButton.delete({ + Key? key, + required enabled, + GestureTapCallback? onTap, + height = defaultButtonHeight * .7, + width = defaultButtonHeight * .7, + }) => + DButton( + key: key, + width: width, + height: height, + onTap: onTap, + child: Tooltip( + child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.remove, size: 18)), + message: LocaleKeys.operation_delete.tr(), + )); + + factory DButton.apply({ + Key? key, + required enabled, + GestureTapCallback? onTap, + height = defaultButtonHeight * .7, + width = defaultButtonHeight * .7, + }) => + DButton( + key: key, + width: width, + height: height, + onTap: onTap, + child: Tooltip( + child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.check, size: 18)), + message: LocaleKeys.operation_apply.tr(), + )); + + factory DButton.duplicate({ + Key? key, + required enabled, + GestureTapCallback? onTap, + height = defaultButtonHeight * .7, + width = defaultButtonHeight * .7, + }) => + DButton( + key: key, + width: width, + height: height, + onTap: onTap, + child: Tooltip( + child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.copy_rounded, size: 18)), + message: LocaleKeys.operation_duplicate.tr(), + )); + @override State createState() => _DButtonState(); } From 6df7543262b806de8f9076b287710cb4f81a6eae Mon Sep 17 00:00:00 2001 From: debuggerx Date: Wed, 13 Oct 2021 01:02:47 +0800 Subject: [PATCH 07/16] feat: make gesture editable. --- app/lib/builder/provider_generator.dart | 6 +- app/lib/models/scheme.dart | 15 ++ app/lib/pages/gesture_editor.dart | 246 ++++++++++++++++++-------------- app/lib/pages/local_manager.dart | 58 -------- app/lib/utils/helper.dart | 1 - 5 files changed, 156 insertions(+), 170 deletions(-) diff --git a/app/lib/builder/provider_generator.dart b/app/lib/builder/provider_generator.dart index 205c260..513fb12 100644 --- a/app/lib/builder/provider_generator.dart +++ b/app/lib/builder/provider_generator.dart @@ -22,7 +22,9 @@ class ProviderGenerator extends GeneratorForAnnotation { List fields = []; element.fields.forEach((field) { var annotation = field.metadata.firstWhereOrNull( - (m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp'); + (m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp') ?? + field.getter?.metadata.firstWhereOrNull( + (m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp'); if (annotation != null) fields.add( AnnotationField( @@ -77,7 +79,7 @@ String? _genCopyFunc(String displayName, List fields, bool copy return ''' void copyFrom(${displayName} other) { bool changed = false; - ${fields.map((f) => 'if (other.${f.name}.diff(this.${f.name})) {this.${f.name} = other.${f.name}; changed = true; }').join('\n')} + ${fields.map((f) => 'if (other.${f.name} != this.${f.name}) {this.${f.name} = other.${f.name}; changed = true; }').join('\n')} if (changed) notifyListeners(); } '''; diff --git a/app/lib/models/scheme.dart b/app/lib/models/scheme.dart index 22be9fb..b3d5d62 100644 --- a/app/lib/models/scheme.dart +++ b/app/lib/models/scheme.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:dde_gesture_manager/builder/provider_annotation.dart'; import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; +import 'package:flutter/material.dart'; @ProviderModel(copyable: true) class Scheme { @@ -76,6 +77,20 @@ class GestureProp { @ProviderModelProp() String? remark; + @ProviderModelProp() + bool get editMode => _editMode; + + set editMode(bool val) { + _editMode = val; + if (val == false) onEditEnd?.call(); + } + + VoidCallback? onEditEnd; + + bool _editMode = false; + + + @override bool operator ==(Object other) => other is GestureProp && diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 11545c5..4e4f56a 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -13,72 +13,6 @@ import 'package:flutter/material.dart'; class GestureEditor extends StatelessWidget { const GestureEditor({Key? key}) : super(key: key); - List _buildDataRow(List? gestures, BuildContext context) => (gestures ?? []).map((gesture) { - bool selected = context.watch() == gesture; - return DDataRow( - onSelectChanged: (selected) { - if (selected == true) - context.read().setProps( - gesture: gesture.gesture, - direction: gesture.direction, - fingers: gesture.fingers, - type: gesture.type, - command: gesture.command, - remark: gesture.remark, - ); - }, - selected: selected, - cells: [ - Center( - child: Text( - '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ).tr(), - ), - Center( - child: Text( - '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ).tr()), - Center( - child: Text( - '${gesture.fingers}', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ), - ), - Center( - child: Text( - '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ).tr()), - Text( - gesture.command ?? '', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ), - Text( - gesture.remark ?? '', - style: TextStyle( - color: selected ? Colors.white : null, - ), - ), - ] - .map( - (ele) => DDataCell(ele), - ) - .toList(), - ); - }).toList(); - @override Widget build(BuildContext context) { var layoutProvider = context.watch(); @@ -131,54 +65,59 @@ class GestureEditor extends StatelessWidget { ), Container(height: 10), Expanded( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(defaultBorderRadius), - border: Border.all( - width: .2, - color: context.t.dividerColor, + child: GestureDetector( + onTap: () { + context.read().copyFrom(GestureProp.empty()); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius), + border: Border.all( + width: .2, + color: context.t.dividerColor, + ), ), - ), - width: double.infinity, - clipBehavior: Clip.antiAlias, - child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - return Scrollbar( - isAlwaysShown: true, - child: SingleChildScrollView( - primary: true, - scrollDirection: Axis.horizontal, - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: constraints.maxWidth), - child: DDataTable( - showCheckboxColumn: true, - headerBackgroundColor: context.t.dialogBackgroundColor, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(defaultBorderRadius), - border: Border.all( - width: .2, - color: context.t.dividerColor, + width: double.infinity, + clipBehavior: Clip.antiAlias, + child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { + return Scrollbar( + isAlwaysShown: true, + child: SingleChildScrollView( + primary: true, + scrollDirection: Axis.horizontal, + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: constraints.maxWidth), + child: DDataTable( + showCheckboxColumn: true, + headerBackgroundColor: context.t.dialogBackgroundColor, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius), + border: Border.all( + width: .2, + color: context.t.dividerColor, + ), ), + dataRowColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; + if (states.contains(MaterialState.selected)) + return context.read().currentActiveColor; + return null; + }), + columns: [ + DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), + DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), + ], + rows: _buildDataRows(schemeProvider.gestures, context), ), - dataRowColor: MaterialStateProperty.resolveWith((Set states) { - if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; - if (states.contains(MaterialState.selected)) - return context.read().currentActiveColor; - return null; - }), - columns: [ - DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), - DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), - ], - rows: _buildDataRow(schemeProvider.gestures, context), ), ), - ), - ); - }), + ); + }), + ), ), ), Container(height: 10), @@ -200,3 +139,92 @@ class GestureEditor extends StatelessWidget { ); } } + +List _buildDataRows(List? gestures, BuildContext context) => (gestures ?? []).map((gesture) { + var gesturePropProvider = context.watch(); + bool editing = gesturePropProvider == gesture && gesturePropProvider.editMode == true; + bool selected = gesturePropProvider == gesture && !editing; + return DDataRow( + onSelectChanged: (selected) { + if (selected == true) + context.read().setProps( + gesture: gesture.gesture, + direction: gesture.direction, + fingers: gesture.fingers, + type: gesture.type, + command: gesture.command, + remark: gesture.remark, + editMode: false, + ); + else if (selected == false) { + var provider = context.read(); + provider.onEditEnd = () { + /// todo: resort rows && check where changed + }; + provider.setProps( + editMode: true, + ); + } + }, + selected: selected, + cells: editing ? _buildRowCellsEditing(gesture) : _buildRowCellsNormal(selected, gesture), + ); + }).toList(); + +List _buildRowCellsEditing(GestureProp gesture) => [ + Text('1'), + Text('2'), + Text('3'), + Text('4'), + TextField(controller: TextEditingController(text: gesture.command)), + TextField(controller: TextEditingController(text: gesture.remark)), + ].map((e) => DDataCell(e)).toList(); + +List _buildRowCellsNormal(bool selected, GestureProp gesture) => [ + Center( + child: Text( + '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ).tr(), + ), + Center( + child: Text( + '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ).tr()), + Center( + child: Text( + '${gesture.fingers}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + ), + Center( + child: Text( + '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ).tr()), + Text( + gesture.command ?? '', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + Text( + gesture.remark ?? '', + style: TextStyle( + color: selected ? Colors.white : null, + ), + ), + ] + .map( + (ele) => DDataCell(ele), + ) + .toList(); diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index 191301e..b4c8218 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -158,64 +158,6 @@ class _LocalManagerState extends State { ), ], ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, index) => GestureDetector( - onDoubleTap: () { - context.read().copyFrom(localSchemes[index].scheme); - setState(() { - _selectedIndex = index; - }); - }, - onTap: () { - setState(() { - _selectedIndex = index; - }); - }, - child: MouseRegion( - cursor: SystemMouseCursors.click, - onEnter: (_) { - setState(() { - _hoveringIndex = index; - }); - }, - child: Container( - color: _getItemBackgroundColor(index), - child: Padding( - padding: const EdgeInsets.only(right: 12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - localSchemes[index].scheme.name ?? '', - style: TextStyle( - color: index == _selectedIndex ? Colors.white : null, - ), - ), - Text( - '456', - style: TextStyle( - color: index == _selectedIndex ? Colors.white : null, - ), - ), - ], - ), - ), - ), - ), - ), - itemCount: localSchemes.length, - ), - ), - Container( - height: 150, - color: Colors.black, - ), - ], ), ), ], diff --git a/app/lib/utils/helper.dart b/app/lib/utils/helper.dart index 2e274fc..4b891ef 100644 --- a/app/lib/utils/helper.dart +++ b/app/lib/utils/helper.dart @@ -103,7 +103,6 @@ class H { var list = inp.split(','); if (list.length != 4) return null; var rgba = list.map((e) => int.parse(e) ~/ 257).toList(); - rgba.sout(); return Color.fromARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } } From bc2b514392ed84b509708c1f813d5b7ada5de7de Mon Sep 17 00:00:00 2001 From: debuggerx Date: Wed, 13 Oct 2021 15:05:57 +0800 Subject: [PATCH 08/16] feat: use CheckedPopupMenuItem instead of PopupMenuItem; use DefaultTextStyle to reduce duplicate code. --- app/lib/constants/supported_locales.dart | 4 ++- app/lib/pages/gesture_editor.dart | 28 +++++------------ app/lib/pages/local_manager.dart | 17 +++++++---- app/lib/widgets/language_switcher.dart | 52 ++++++++++++++------------------ app/lib/widgets/theme_switcher.dart | 40 +++++++++--------------- 5 files changed, 58 insertions(+), 83 deletions(-) diff --git a/app/lib/constants/supported_locales.dart b/app/lib/constants/supported_locales.dart index 0897879..0524221 100644 --- a/app/lib/constants/supported_locales.dart +++ b/app/lib/constants/supported_locales.dart @@ -18,5 +18,7 @@ const supportedLocaleNames = { SupportedLocale.en: 'English', }; -Locale getSupportedLocale(SupportedLocale supportedLocale) => supportedLocales[supportedLocale.index]; +Locale transformSupportedLocale(SupportedLocale supportedLocale) => supportedLocales[supportedLocale.index]; +SupportedLocale? getSupportedLocale(Locale? locale) => + supportedLocales.contains(locale) ? SupportedLocale.values[supportedLocales.indexOf(locale!)] : null; diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 4e4f56a..31d4d86 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -167,7 +167,7 @@ List _buildDataRows(List? gestures, BuildContext context) } }, selected: selected, - cells: editing ? _buildRowCellsEditing(gesture) : _buildRowCellsNormal(selected, gesture), + cells: editing ? _buildRowCellsEditing(gesture) : _buildRowCellsNormal(context, selected, gesture), ); }).toList(); @@ -180,51 +180,37 @@ List _buildRowCellsEditing(GestureProp gesture) => [ TextField(controller: TextEditingController(text: gesture.remark)), ].map((e) => DDataCell(e)).toList(); -List _buildRowCellsNormal(bool selected, GestureProp gesture) => [ +List _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [ Center( child: Text( '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), ).tr(), ), Center( child: Text( '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), ).tr()), Center( child: Text( '${gesture.fingers}', - style: TextStyle( - color: selected ? Colors.white : null, - ), ), ), Center( child: Text( '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', - style: TextStyle( - color: selected ? Colors.white : null, - ), ).tr()), Text( gesture.command ?? '', - style: TextStyle( - color: selected ? Colors.white : null, - ), ), Text( gesture.remark ?? '', - style: TextStyle( - color: selected ? Colors.white : null, - ), ), ] .map( - (ele) => DDataCell(ele), + (ele) => DDataCell(DefaultTextStyle( + style: context.t.textTheme.bodyText2!.copyWith( + color: selected ? Colors.white : null, + ), + child: ele)), ) .toList(); diff --git a/app/lib/pages/local_manager.dart b/app/lib/pages/local_manager.dart index b4c8218..137ba5e 100644 --- a/app/lib/pages/local_manager.dart +++ b/app/lib/pages/local_manager.dart @@ -123,12 +123,17 @@ class _LocalManagerState extends State { color: _getItemBackgroundColor(index), child: Padding( padding: const EdgeInsets.only(left: 6, right: 12.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(localSchemes[index].scheme.name ?? ''), - Text('456'), - ], + child: DefaultTextStyle( + style: context.t.textTheme.bodyText2!.copyWith( + color: _selectedIndex == index ? Colors.white : null, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(localSchemes[index].scheme.name ?? ''), + Text('456'), + ], + ), ), ), ), diff --git a/app/lib/widgets/language_switcher.dart b/app/lib/widgets/language_switcher.dart index 16db130..e98317d 100644 --- a/app/lib/widgets/language_switcher.dart +++ b/app/lib/widgets/language_switcher.dart @@ -1,4 +1,3 @@ -import 'package:collection/collection.dart'; import 'package:dde_gesture_manager/constants/sp_keys.dart'; import 'package:dde_gesture_manager/constants/supported_locales.dart'; import 'package:dde_gesture_manager/extensions.dart'; @@ -6,7 +5,6 @@ import 'package:dde_gesture_manager/generated/codegen_loader.g.dart'; import 'package:dde_gesture_manager/generated/locale_keys.g.dart'; import 'package:dde_gesture_manager/models/local_schemes_provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; @@ -18,7 +16,7 @@ class LanguageSwitcher extends StatelessWidget { @override Widget build(BuildContext context) { var _locale = EasyLocalization.of(context)?.currentLocale; - var _supportedLocale = supportedLocales.firstWhereOrNull((element) => element == _locale); + var _supportedLocale = getSupportedLocale(_locale) ?? SupportedLocale.zh_CN; return PopupMenuButton( tooltip: LocaleKeys.language_tip.tr(), @@ -31,33 +29,29 @@ class LanguageSwitcher extends StatelessWidget { ), ], ), - itemBuilder: (BuildContext context) => supportedLocales + initialValue: _supportedLocale, + onSelected: (value) { + EasyLocalization.of(context)?.setLocale(transformSupportedLocale(value)).then((_) { + var localeMap = Translations(CodegenLoader.mapLocales[context.locale.toString()]!); + if (!kIsWeb) WindowManager.instance.setTitle(localeMap.get(LocaleKeys.app_name)!); + var localSchemesProvider = context.read(); + var schemes = localSchemesProvider.schemes!; + var newSchemes = [ + schemes.first + ..scheme.name = localeMap.get(LocaleKeys.local_manager_default_scheme_label) + ..scheme.description = localeMap.get(LocaleKeys.local_manager_default_scheme_description), + ...schemes.skip(1), + ]; + localSchemesProvider.setProps(schemes: newSchemes); + }); + H().sp.setInt(SPKeys.userLanguage, value.index); + }, + itemBuilder: (BuildContext context) => SupportedLocale.values .map( - (locale) => PopupMenuItem( - value: SupportedLocale.zh_CN, - child: ListTile( - leading: Visibility( - child: Icon(CupertinoIcons.check_mark), - visible: _supportedLocale == locale, - ), - title: Text(supportedLocaleNames[SupportedLocale.values[supportedLocales.indexOf(locale)]] ?? ''), - ), - onTap: () { - EasyLocalization.of(context)?.setLocale(locale).then((_) { - var localeMap = Translations(CodegenLoader.mapLocales[context.locale.toString()]!); - if (!kIsWeb) WindowManager.instance.setTitle(localeMap.get(LocaleKeys.app_name)!); - var localSchemesProvider = context.read(); - var schemes = localSchemesProvider.schemes!; - var newSchemes = [ - schemes.first - ..scheme.name = localeMap.get(LocaleKeys.local_manager_default_scheme_label) - ..scheme.description = localeMap.get(LocaleKeys.local_manager_default_scheme_description), - ...schemes.skip(1), - ]; - localSchemesProvider.setProps(schemes: newSchemes); - }); - H().sp.setInt(SPKeys.userLanguage, supportedLocales.indexOf(locale)); - }, + (supportedLocale) => CheckedPopupMenuItem( + value: supportedLocale, + checked: EasyLocalization.of(context)?.locale == transformSupportedLocale(supportedLocale), + child: Text(supportedLocaleNames[supportedLocale] ?? ''), ), ) .toList(), diff --git a/app/lib/widgets/theme_switcher.dart b/app/lib/widgets/theme_switcher.dart index a0f4df8..3ad2537 100644 --- a/app/lib/widgets/theme_switcher.dart +++ b/app/lib/widgets/theme_switcher.dart @@ -11,7 +11,7 @@ class ThemeSwitcher extends StatelessWidget { @override Widget build(BuildContext context) { var _brightnessMode = context.watch().brightnessMode; - return PopupMenuButton( + return PopupMenuButton( initialValue: _brightnessMode, child: Row( children: [ @@ -23,35 +23,23 @@ class ThemeSwitcher extends StatelessWidget { ], ), padding: EdgeInsets.zero, + onSelected: (value) => context.read().setProps(brightnessMode: value), tooltip: LocaleKeys.theme_tip.tr(), itemBuilder: (BuildContext context) => [ - PopupMenuItem( - child: ListTile( - leading: Visibility( - child: Icon(CupertinoIcons.check_mark), - visible: _brightnessMode == BrightnessMode.system, - ), - title: Text(LocaleKeys.theme_system).tr(), - ), - onTap: () => context.read().setProps(brightnessMode: BrightnessMode.system), + CheckedPopupMenuItem( + child: Text(LocaleKeys.theme_system).tr(), + checked: _brightnessMode == BrightnessMode.system, + value: BrightnessMode.system, ), - PopupMenuItem( - child: ListTile( - leading: Visibility( - child: Icon(CupertinoIcons.check_mark), - visible: _brightnessMode == BrightnessMode.light, - ), - title: Text(LocaleKeys.theme_light).tr()), - onTap: () => context.read().setProps(brightnessMode: BrightnessMode.light), + CheckedPopupMenuItem( + child: Text(LocaleKeys.theme_light).tr(), + checked: _brightnessMode == BrightnessMode.light, + value: BrightnessMode.light, ), - PopupMenuItem( - child: ListTile( - leading: Visibility( - child: Icon(CupertinoIcons.check_mark), - visible: _brightnessMode == BrightnessMode.dark, - ), - title: Text(LocaleKeys.theme_dark).tr()), - onTap: () => context.read().setProps(brightnessMode: BrightnessMode.dark), + CheckedPopupMenuItem( + child: Text(LocaleKeys.theme_dark).tr(), + checked: _brightnessMode == BrightnessMode.dark, + value: BrightnessMode.dark, ), ], ); From 76b6c14553913ce4d524d4c38f0e52760f181d58 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Tue, 2 Nov 2021 19:19:13 +0800 Subject: [PATCH 09/16] feat: use adaptive_scrollbar instead of scrollbar; add uuid to GestureProp. --- app/lib/models/scheme.dart | 20 ++++--- app/lib/pages/gesture_editor.dart | 116 ++++++++++++++++++++++-------------- app/lib/widgets/dde_data_table.dart | 3 + app/pubspec.yaml | 2 + 4 files changed, 87 insertions(+), 54 deletions(-) diff --git a/app/lib/models/scheme.dart b/app/lib/models/scheme.dart index b3d5d62..cb00d4c 100644 --- a/app/lib/models/scheme.dart +++ b/app/lib/models/scheme.dart @@ -4,6 +4,7 @@ import 'package:dde_gesture_manager/builder/provider_annotation.dart'; import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:flutter/material.dart'; +import 'package:uuid/uuid.dart'; @ProviderModel(copyable: true) class Scheme { @@ -29,10 +30,15 @@ class Scheme { } Scheme.systemDefault() { + this.id = Uuid.NAMESPACE_NIL; this.name = LocaleKeys.local_manager_default_scheme_label.tr(); this.description = LocaleKeys.local_manager_default_scheme_description.tr(); this.gestures = []; } + + Scheme.create({this.name, this.description, this.gestures}) { + this.id = Uuid().v1(); + } } enum Gesture { @@ -60,6 +66,9 @@ enum GestureType { @ProviderModel(copyable: true) class GestureProp { @ProviderModelProp() + String? id; + + @ProviderModelProp() Gesture? gesture; @ProviderModelProp() @@ -89,25 +98,20 @@ class GestureProp { bool _editMode = false; - - @override - bool operator ==(Object other) => - other is GestureProp && - other.gesture == this.gesture && - other.direction == this.direction && - other.fingers == this.fingers; + bool operator ==(Object other) => other is GestureProp && other.id == this.id; @override String toString() { return 'GestureProp{gesture: $gesture, direction: $direction, fingers: $fingers, type: $type, command: $command, remark: $remark}'; } - GestureProp.empty(); + GestureProp.empty() : this.id = Uuid.NAMESPACE_NIL; GestureProp.parse(props) { if (props is String) props = json.decode(props); assert(props is Map); + id = Uuid().v1(); gesture = H.getGestureByName(props['gesture']); direction = H.getGestureDirectionByName(props['direction']); fingers = props['fingers']; diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 31d4d86..485114d 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -1,3 +1,4 @@ +import 'package:adaptive_scrollbar/adaptive_scrollbar.dart'; import 'package:dde_gesture_manager/constants/constants.dart'; import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/content_layout.provider.dart'; @@ -10,6 +11,9 @@ import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +const double _headingRowHeight = 56; +const double _scrollBarWidth = 14; + class GestureEditor extends StatelessWidget { const GestureEditor({Key? key}) : super(key: key); @@ -17,6 +21,9 @@ class GestureEditor extends StatelessWidget { Widget build(BuildContext context) { var layoutProvider = context.watch(); var schemeProvider = context.watch(); + final horizontalCtrl = ScrollController(); + final verticalCtrl = ScrollController(); + return Flexible( child: Padding( padding: const EdgeInsets.all(10), @@ -80,38 +87,60 @@ class GestureEditor extends StatelessWidget { width: double.infinity, clipBehavior: Clip.antiAlias, child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { - return Scrollbar( - isAlwaysShown: true, - child: SingleChildScrollView( - primary: true, - scrollDirection: Axis.horizontal, - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: constraints.maxWidth), - child: DDataTable( - showCheckboxColumn: true, - headerBackgroundColor: context.t.dialogBackgroundColor, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(defaultBorderRadius), - border: Border.all( - width: .2, - color: context.t.dividerColor, - ), + return AdaptiveScrollbar( + controller: verticalCtrl, + underColor: Colors.transparent, + sliderDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + color: Colors.grey.withOpacity(.4), + ), + sliderActiveDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + color: Colors.grey.withOpacity(.6), + ), + position: ScrollbarPosition.right, + underSpacing: EdgeInsets.only(top: _headingRowHeight), + width: _scrollBarWidth, + child: AdaptiveScrollbar( + width: _scrollBarWidth, + underColor: Colors.transparent, + sliderDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + color: Colors.grey.withOpacity(.4), + ), + sliderActiveDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + color: Colors.grey.withOpacity(.6), + ), + controller: horizontalCtrl, + position: ScrollbarPosition.bottom, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: horizontalCtrl, + child: ConstrainedBox( + constraints: BoxConstraints(minWidth: constraints.maxWidth), + child: DDataTable( + showBottomBorder: true, + headingRowHeight: _headingRowHeight, + showCheckboxColumn: true, + headerBackgroundColor: context.t.dialogBackgroundColor, + verticalScrollController: verticalCtrl, + dataRowColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; + if (states.contains(MaterialState.selected)) + return context.read().currentActiveColor; + return null; + }), + columns: [ + DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), + DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), + ], + rows: _buildDataRows(schemeProvider.gestures, context), ), - dataRowColor: MaterialStateProperty.resolveWith((Set states) { - if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; - if (states.contains(MaterialState.selected)) - return context.read().currentActiveColor; - return null; - }), - columns: [ - DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), - DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), - ], - rows: _buildDataRows(schemeProvider.gestures, context), ), ), ), @@ -148,12 +177,7 @@ List _buildDataRows(List? gestures, BuildContext context) onSelectChanged: (selected) { if (selected == true) context.read().setProps( - gesture: gesture.gesture, - direction: gesture.direction, - fingers: gesture.fingers, - type: gesture.type, - command: gesture.command, - remark: gesture.remark, + id: gesture.id, editMode: false, ); else if (selected == false) { @@ -172,10 +196,10 @@ List _buildDataRows(List? gestures, BuildContext context) }).toList(); List _buildRowCellsEditing(GestureProp gesture) => [ - Text('1'), - Text('2'), - Text('3'), - Text('4'), + Center(child: Text('1')), + Center(child: Text('2')), + Center(child: Text('3')), + Center(child: Text('4')), TextField(controller: TextEditingController(text: gesture.command)), TextField(controller: TextEditingController(text: gesture.remark)), ].map((e) => DDataCell(e)).toList(); @@ -183,6 +207,11 @@ List _buildRowCellsEditing(GestureProp gesture) => [ List _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [ Center( child: Text( + '${gesture.fingers}', + ), + ), + Center( + child: Text( '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(gesture.gesture)}', ).tr(), ), @@ -191,11 +220,6 @@ List _buildRowCellsNormal(BuildContext context, bool selected, Gestur '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(gesture.direction)}', ).tr()), Center( - child: Text( - '${gesture.fingers}', - ), - ), - Center( child: Text( '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', ).tr()), diff --git a/app/lib/widgets/dde_data_table.dart b/app/lib/widgets/dde_data_table.dart index 2e032ee..5a7b90a 100644 --- a/app/lib/widgets/dde_data_table.dart +++ b/app/lib/widgets/dde_data_table.dart @@ -420,6 +420,7 @@ class DDataCell { /// * class DDataTable extends StatefulWidget { final Color headerBackgroundColor; + final ScrollController verticalScrollController; /// Creates a widget describing a data table. /// @@ -466,6 +467,7 @@ class DDataTable extends StatefulWidget { required this.rows, this.checkboxHorizontalMargin, required this.headerBackgroundColor, + required this.verticalScrollController, }) : assert(columns != null), assert(columns.isNotEmpty), assert(sortColumnIndex == null || (sortColumnIndex >= 0 && sortColumnIndex < columns.length)), @@ -1033,6 +1035,7 @@ class _DDataTableState extends State { padding: EdgeInsets.only(top: _headersRect?.last.height ?? 0), child: SingleChildScrollView( scrollDirection: Axis.vertical, + controller: widget.verticalScrollController, child: Transform.translate( offset: Offset(0, -(_headersRect?.last.height ?? 0)), child: Table( diff --git a/app/pubspec.yaml b/app/pubspec.yaml index d76ae6c..b751a2c 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -35,6 +35,8 @@ dependencies: glass_kit: ^2.0.1 rect_getter: ^1.0.0 path_provider: ^2.0.5 + uuid: ^3.0.5 + adaptive_scrollbar: ^2.1.0 xdg_directories_web: path: 3rd_party/xdg_directories_web From 2484367337bc155b9ae4f5acf539536217665216 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Thu, 4 Nov 2021 18:48:59 +0800 Subject: [PATCH 10/16] wip: sort gesture props when edit end. --- app/lib/models/scheme.dart | 40 ++++++++++++++++++++++------- app/lib/pages/gesture_editor.dart | 53 ++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 23 deletions(-) diff --git a/app/lib/models/scheme.dart b/app/lib/models/scheme.dart index cb00d4c..4b54d4f 100644 --- a/app/lib/models/scheme.dart +++ b/app/lib/models/scheme.dart @@ -2,10 +2,12 @@ import 'dart:convert'; import 'package:dde_gesture_manager/builder/provider_annotation.dart'; import 'package:dde_gesture_manager/extensions.dart'; +import 'package:dde_gesture_manager/extensions/compare_extension.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; -import 'package:flutter/material.dart'; import 'package:uuid/uuid.dart'; +typedef OnEditEnd(GestureProp prop); + @ProviderModel(copyable: true) class Scheme { @ProviderModelProp() @@ -26,7 +28,7 @@ class Scheme { id = scheme['id']; name = scheme['name']; description = scheme['desc']; - gestures = (scheme['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList(); + gestures = (scheme['gestures'] as List? ?? []).map((ele) => GestureProp.parse(ele)).toList()..sort(); } Scheme.systemDefault() { @@ -42,8 +44,8 @@ class Scheme { } enum Gesture { - swipe, tap, + swipe, pinch, } @@ -64,7 +66,7 @@ enum GestureType { } @ProviderModel(copyable: true) -class GestureProp { +class GestureProp implements Comparable { @ProviderModelProp() String? id; @@ -87,14 +89,14 @@ class GestureProp { String? remark; @ProviderModelProp() - bool get editMode => _editMode; + bool? get editMode => _editMode; - set editMode(bool val) { - _editMode = val; - if (val == false) onEditEnd?.call(); + set editMode(bool? val) { + _editMode = val ?? false; + if (val == false) onEditEnd?.call(this); } - VoidCallback? onEditEnd; + OnEditEnd? onEditEnd; bool _editMode = false; @@ -119,4 +121,24 @@ class GestureProp { command = props['command']; remark = props['remark']; } + + copyFrom(GestureProp prop) { + this.id = prop.id; + this.gesture = prop.gesture; + this.direction = prop.direction; + this.fingers = prop.fingers; + this.type = prop.type; + this.command = prop.command; + this.remark = prop.remark; + } + + @override + int compareTo(other) { + assert(other is GestureProp); + if (fingers.diff(other.fingers) && other.fingers != null) return fingers! - other.fingers as int; + if (gesture.diff(other.gesture) && other.gesture != null) return gesture!.index - other.gesture!.index as int; + if (direction.diff(other.direction) && other.direction != null) + return direction!.index - other.direction!.index as int; + return 0; + } } diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 485114d..f59423d 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -74,7 +74,7 @@ class GestureEditor extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - context.read().copyFrom(GestureProp.empty()); + context.read().setProps(editMode: false); }, child: Container( decoration: BoxDecoration( @@ -175,28 +175,53 @@ List _buildDataRows(List? gestures, BuildContext context) bool selected = gesturePropProvider == gesture && !editing; return DDataRow( onSelectChanged: (selected) { - if (selected == true) - context.read().setProps( + var provider = context.read(); + if (selected == true) { + provider.setProps( + editMode: false, + ); + Future.microtask(() => provider.setProps( id: gesture.id, - editMode: false, - ); - else if (selected == false) { - var provider = context.read(); - provider.onEditEnd = () { - /// todo: resort rows && check where changed + )); + } else if (selected == false) { + provider.onEditEnd = (prop) { + var schemeProvider = context.read(); + var newGestures = List.of(schemeProvider.gestures!); + var index = newGestures.indexWhere((element) => element == prop); + newGestures[index].copyFrom(prop); + context.read().setProps( + gestures: newGestures..sort(), + ); }; - provider.setProps( - editMode: true, + provider.copyFrom( + gesture..editMode = true, ); } }, selected: selected, - cells: editing ? _buildRowCellsEditing(gesture) : _buildRowCellsNormal(context, selected, gesture), + cells: editing ? _buildRowCellsEditing(context, gesture) : _buildRowCellsNormal(context, selected, gesture), ); }).toList(); -List _buildRowCellsEditing(GestureProp gesture) => [ - Center(child: Text('1')), +List _buildRowCellsEditing(BuildContext context, GestureProp gesture) => [ + Container( + decoration: BoxDecoration( + color: Colors.lightBlue, + ), + child: DropdownButton( + items: [3, 4, 5] + .map( + (e) => DropdownMenuItem( + child: Text('$e'), + value: e, + ), + ) + .toList(), + value: context.watch().fingers, + onChanged: (value) => context.read().setProps(fingers: value, editMode: true), + isExpanded: true, + ), + ), Center(child: Text('2')), Center(child: Text('3')), Center(child: Text('4')), From eeeaba3c0ad0b9909931eb9b0152a75e6f866580 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Fri, 5 Nov 2021 18:35:41 +0800 Subject: [PATCH 11/16] wip: DropdownButton and TextField on DataTable. --- app/lib/pages/gesture_editor.dart | 106 ++++++++++++++++++++++++++--- app/lib/widgets/dde_button.dart | 29 +++++++- app/lib/widgets/table_cell_text_field.dart | 73 ++++++++++++++++++++ 3 files changed, 195 insertions(+), 13 deletions(-) create mode 100644 app/lib/widgets/table_cell_text_field.dart diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index f59423d..2d73620 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -8,6 +8,7 @@ import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; +import 'package:dde_gesture_manager/widgets/table_cell_text_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -204,11 +205,10 @@ List _buildDataRows(List? gestures, BuildContext context) }).toList(); List _buildRowCellsEditing(BuildContext context, GestureProp gesture) => [ - Container( - decoration: BoxDecoration( - color: Colors.lightBlue, - ), + DButton.dropdown( + enabled: true, child: DropdownButton( + icon: Icon(Icons.keyboard_arrow_down_rounded), items: [3, 4, 5] .map( (e) => DropdownMenuItem( @@ -218,15 +218,101 @@ List _buildRowCellsEditing(BuildContext context, GestureProp gesture) ) .toList(), value: context.watch().fingers, - onChanged: (value) => context.read().setProps(fingers: value, editMode: true), + onChanged: (value) => context.read().setProps( + fingers: value, + editMode: true, + ), isExpanded: true, ), ), - Center(child: Text('2')), - Center(child: Text('3')), - Center(child: Text('4')), - TextField(controller: TextEditingController(text: gesture.command)), - TextField(controller: TextEditingController(text: gesture.remark)), + DButton.dropdown( + enabled: true, + width: 60.0, + child: DropdownButton( + icon: Icon(Icons.keyboard_arrow_down_rounded), + items: Gesture.values + .map( + (e) => DropdownMenuItem( + child: Text( + '${LocaleKeys.gesture_editor_gestures}.${H.getGestureName(e)}', + textScaleFactor: .8, + ).tr(), + value: e, + ), + ) + .toList(), + value: context.watch().gesture, + onChanged: (value) => context.read().setProps( + gesture: value, + editMode: true, + ), + isExpanded: true, + ), + ), + DButton.dropdown( + enabled: true, + width: 100.0, + child: DropdownButton( + icon: Icon(Icons.keyboard_arrow_down_rounded), + items: GestureDirection.values + .map( + (e) => DropdownMenuItem( + child: Text( + '${LocaleKeys.gesture_editor_directions}.${H.getGestureDirectionName(e)}', + textScaleFactor: .8, + ).tr(), + value: e, + ), + ) + .toList(), + value: context.watch().direction, + onChanged: (value) => context.read().setProps( + direction: value, + editMode: true, + ), + isExpanded: true, + ), + ), + DButton.dropdown( + enabled: true, + width: 100.0, + child: DropdownButton( + icon: Icon(Icons.keyboard_arrow_down_rounded), + items: GestureType.values + .map( + (e) => DropdownMenuItem( + child: Text( + '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(e)}', + textScaleFactor: .8, + ).tr(), + value: e, + ), + ) + .toList(), + value: context.watch().type, + onChanged: (value) => context.read().setProps( + type: value, + editMode: true, + ), + isExpanded: true, + ), + ), + TableCellTextField( + initText: gesture.command, + hint: 'pls input cmd', + onComplete: (value) => context.read().setProps( + command: value, + editMode: true, + ), + ), + TableCellTextField( + initText: gesture.remark, + hint: 'pls input cmd', + onComplete: (value) => context.read().setProps( + remark: value, + editMode: true, + ), + ), ].map((e) => DDataCell(e)).toList(); List _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [ diff --git a/app/lib/widgets/dde_button.dart b/app/lib/widgets/dde_button.dart index faabfc4..ce54464 100644 --- a/app/lib/widgets/dde_button.dart +++ b/app/lib/widgets/dde_button.dart @@ -1,5 +1,6 @@ import 'package:dde_gesture_manager/constants/constants.dart'; import 'package:dde_gesture_manager/extensions.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:flutter/material.dart'; import 'package:glass_kit/glass_kit.dart'; @@ -8,6 +9,8 @@ class DButton extends StatefulWidget { final double height; final Widget child; final GestureTapCallback? onTap; + final EdgeInsets? padding; + final Color? activeBorderColor; const DButton({ Key? key, @@ -15,6 +18,8 @@ class DButton extends StatefulWidget { this.height = defaultButtonHeight, required this.child, this.onTap, + this.padding, + this.activeBorderColor, }) : super(key: key); factory DButton.add({ @@ -85,6 +90,22 @@ class DButton extends StatefulWidget { message: LocaleKeys.operation_duplicate.tr(), )); + factory DButton.dropdown({ + Key? key, + width = 60.0, + height = kMinInteractiveDimension * .86, + padding: const EdgeInsets.only(left: 15), + required enabled, + required DropdownButton child, + }) => + DButton( + key: key, + width: width, + height: height, + padding: padding, + child: child, + ); + @override State createState() => _DButtonState(); } @@ -95,8 +116,9 @@ class _DButtonState extends State { @override Widget build(BuildContext context) { return GestureDetector( - onTap: widget.onTap, + onTap: widget.child is DropdownButton ? (widget.child as DropdownButton).onTap : widget.onTap, child: GlassContainer( + padding: widget.padding, width: widget.width, height: widget.height, gradient: LinearGradient( @@ -104,8 +126,9 @@ class _DButtonState extends State { begin: Alignment.topCenter, end: Alignment.bottomCenter, ), - borderColor: Color(0xff565656), - borderWidth: 1, + borderColor: + _hovering ? widget.activeBorderColor ?? context.watch().activeColor : Color(0xff565656), + borderWidth: 2, borderRadius: BorderRadius.circular(defaultBorderRadius), child: MouseRegion( onEnter: (event) => setState(() { diff --git a/app/lib/widgets/table_cell_text_field.dart b/app/lib/widgets/table_cell_text_field.dart new file mode 100644 index 0000000..0e32bbd --- /dev/null +++ b/app/lib/widgets/table_cell_text_field.dart @@ -0,0 +1,73 @@ +import 'package:dde_gesture_manager/constants/constants.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class TableCellTextField extends StatefulWidget { + final String? initText; + final String? hint; + final Function(String value) onComplete; + + const TableCellTextField({ + Key? key, + this.initText, + this.hint, + required this.onComplete, + }) : super(key: key); + + @override + _TableCellTextFieldState createState() => _TableCellTextFieldState(); +} + +class _TableCellTextFieldState extends State { + final FocusNode _focusNode = FocusNode(); + final TextEditingController _controller = TextEditingController(); + + @override + void initState() { + _focusNode.addListener(_handleFocusChange); + _controller.text = widget.initText ?? ''; + super.initState(); + } + + @override + void dispose() { + _focusNode.removeListener(_handleFocusChange); + super.dispose(); + } + + _handleFocusChange() { + if (!_focusNode.hasFocus) { + widget.onComplete(_controller.text); + } + } + + @override + Widget build(BuildContext context) { + return Container( + height: kMinInteractiveDimension * .86, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius), + color: Colors.grey.withOpacity(.3), + border: Border.all( + width: 2, + color: Focus.of(context).hasFocus + ? context.watch().activeColor ?? + Color(0xff565656) + : Color(0xff565656)), + ), + child: Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: EdgeInsets.only(left: 15), + child: TextField( + focusNode: _focusNode, + cursorColor: context.watch().activeColor, + decoration: InputDecoration.collapsed(hintText: widget.hint), + controller: _controller, + ), + ), + ), + ); + } +} From 4eb7bc256ceb70b9639ea770ab782d811a5387ff Mon Sep 17 00:00:00 2001 From: debuggerx Date: Tue, 9 Nov 2021 18:38:44 +0800 Subject: [PATCH 12/16] wip: shortcut listener widget. --- app/lib/constants/constants.dart | 15 ++ app/lib/pages/gesture_editor.dart | 160 +++++++++++++++++----- app/lib/widgets/table_cell_shortcut_listener.dart | 105 ++++++++++++++ app/lib/widgets/table_cell_text_field.dart | 4 +- 4 files changed, 251 insertions(+), 33 deletions(-) create mode 100644 app/lib/widgets/table_cell_shortcut_listener.dart diff --git a/app/lib/constants/constants.dart b/app/lib/constants/constants.dart index 848ac13..dfee4a3 100644 --- a/app/lib/constants/constants.dart +++ b/app/lib/constants/constants.dart @@ -20,6 +20,21 @@ const double defaultBorderRadius = 8; const double defaultButtonHeight = 36; +const List builtInCommands = [ + 'ShowWorkspace', + 'ToggleMaximize', + 'Minimize', + 'ShowWindow', + 'ShowAllWindow', + 'SwitchApplication', + 'ReverseSwitchApplication', + 'SwitchWorkspace', + 'ReverseSwitchWorkspace', + 'SplitWindowLeft', + 'SplitWindowRight', + 'MoveWindow', +]; + enum PanelType { local_manager, market, diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index 2d73620..e5d00ff 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -8,6 +8,7 @@ import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; +import 'package:dde_gesture_manager/widgets/table_cell_shortcut_listener.dart'; import 'package:dde_gesture_manager/widgets/table_cell_text_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -46,7 +47,8 @@ class GestureEditor extends StatelessWidget { visible: layoutProvider.localManagerOpened == false, child: DButton( width: defaultButtonHeight, - onTap: () => H.openPanel(context, PanelType.local_manager), + onTap: () => + H.openPanel(context, PanelType.local_manager), child: Icon( CupertinoIcons.square_list, ), @@ -75,11 +77,14 @@ class GestureEditor extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - context.read().setProps(editMode: false); + context + .read() + .setProps(editMode: false); }, child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(defaultBorderRadius), + borderRadius: + BorderRadius.circular(defaultBorderRadius), border: Border.all( width: .2, color: context.t.dividerColor, @@ -87,16 +92,19 @@ class GestureEditor extends StatelessWidget { ), width: double.infinity, clipBehavior: Clip.antiAlias, - child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { + child: LayoutBuilder(builder: + (BuildContext context, BoxConstraints constraints) { return AdaptiveScrollbar( controller: verticalCtrl, underColor: Colors.transparent, sliderDecoration: BoxDecoration( - borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: + BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.4), ), sliderActiveDecoration: BoxDecoration( - borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: + BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.6), ), position: ScrollbarPosition.right, @@ -106,11 +114,13 @@ class GestureEditor extends StatelessWidget { width: _scrollBarWidth, underColor: Colors.transparent, sliderDecoration: BoxDecoration( - borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: + BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.4), ), sliderActiveDecoration: BoxDecoration( - borderRadius: BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: + BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.6), ), controller: horizontalCtrl, @@ -119,28 +129,58 @@ class GestureEditor extends StatelessWidget { scrollDirection: Axis.horizontal, controller: horizontalCtrl, child: ConstrainedBox( - constraints: BoxConstraints(minWidth: constraints.maxWidth), + constraints: BoxConstraints( + minWidth: constraints.maxWidth), child: DDataTable( showBottomBorder: true, headingRowHeight: _headingRowHeight, showCheckboxColumn: true, - headerBackgroundColor: context.t.dialogBackgroundColor, + headerBackgroundColor: + context.t.dialogBackgroundColor, verticalScrollController: verticalCtrl, - dataRowColor: MaterialStateProperty.resolveWith((Set states) { - if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; + dataRowColor: + MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.hovered)) + return context.t.dialogBackgroundColor; if (states.contains(MaterialState.selected)) - return context.read().currentActiveColor; + return context + .read() + .currentActiveColor; return null; }), columns: [ - DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), - DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), - DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_fingers + .tr()), + center: true), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_gesture + .tr()), + center: true), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_direction + .tr()), + center: true), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_type + .tr()), + center: true), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_command + .tr())), + DDataColumn( + label: Text(LocaleKeys + .gesture_editor_remark + .tr())), ], - rows: _buildDataRows(schemeProvider.gestures, context), + rows: _buildDataRows( + schemeProvider.gestures, context), ), ), ), @@ -170,9 +210,12 @@ class GestureEditor extends StatelessWidget { } } -List _buildDataRows(List? gestures, BuildContext context) => (gestures ?? []).map((gesture) { +List _buildDataRows( + List? gestures, BuildContext context) => + (gestures ?? []).map((gesture) { var gesturePropProvider = context.watch(); - bool editing = gesturePropProvider == gesture && gesturePropProvider.editMode == true; + bool editing = gesturePropProvider == gesture && + gesturePropProvider.editMode == true; bool selected = gesturePropProvider == gesture && !editing; return DDataRow( onSelectChanged: (selected) { @@ -200,11 +243,15 @@ List _buildDataRows(List? gestures, BuildContext context) } }, selected: selected, - cells: editing ? _buildRowCellsEditing(context, gesture) : _buildRowCellsNormal(context, selected, gesture), + cells: editing + ? _buildRowCellsEditing(context, gesture) + : _buildRowCellsNormal(context, selected, gesture), ); }).toList(); -List _buildRowCellsEditing(BuildContext context, GestureProp gesture) => [ +List _buildRowCellsEditing( + BuildContext context, GestureProp gesture) => + [ DButton.dropdown( enabled: true, child: DropdownButton( @@ -297,25 +344,74 @@ List _buildRowCellsEditing(BuildContext context, GestureProp gesture) isExpanded: true, ), ), + _buildCommandCellsEditing(context), TableCellTextField( - initText: gesture.command, + initText: gesture.remark, hint: 'pls input cmd', onComplete: (value) => context.read().setProps( - command: value, + remark: value, editMode: true, ), ), - TableCellTextField( - initText: gesture.remark, + ].map((e) => DDataCell(e)).toList(); + +Widget _buildCommandCellsEditing(BuildContext context) { + 'build cmd cell'.sout(); + var gesture = context.read(); + switch (gesture.type) { + case GestureType.commandline: + return TableCellTextField( + initText: gesture.command, hint: 'pls input cmd', onComplete: (value) => context.read().setProps( - remark: value, + command: value, editMode: true, ), - ), - ].map((e) => DDataCell(e)).toList(); + ); + case GestureType.built_in: + return DButton.dropdown( + enabled: true, + width: 250.0, + child: DropdownButton( + icon: Icon(Icons.keyboard_arrow_down_rounded), + items: builtInCommands + .map( + (e) => DropdownMenuItem( + child: Text( + e, + textScaleFactor: .8, + ), + value: e, + ), + ) + .toList(), + value: builtInCommands.contains(gesture.command) + ? gesture.command + : builtInCommands.first, + onChanged: (value) => context.read().setProps( + command: value, + editMode: true, + ), + isExpanded: true, + ), + ); + case GestureType.shortcut: + return TableCellShortcutListener( + width: 150.0, + initShortcut: gesture.command ?? '', + onComplete: (value) => context.read().setProps( + command: value, + editMode: true, + ), + ); + default: + throw Exception('Unknown gesture command type.'); + } +} -List _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [ +List _buildRowCellsNormal( + BuildContext context, bool selected, GestureProp gesture) => + [ Center( child: Text( '${gesture.fingers}', diff --git a/app/lib/widgets/table_cell_shortcut_listener.dart b/app/lib/widgets/table_cell_shortcut_listener.dart new file mode 100644 index 0000000..fc8a963 --- /dev/null +++ b/app/lib/widgets/table_cell_shortcut_listener.dart @@ -0,0 +1,105 @@ +import 'package:dde_gesture_manager/constants/constants.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:flutter/material.dart'; +import 'package:dde_gesture_manager/extensions.dart'; + +class TableCellShortcutListener extends StatefulWidget { + final double width; + final String initShortcut; + final Function(String shortcut) onComplete; + + const TableCellShortcutListener({ + Key? key, + this.width = 150.0, + required this.initShortcut, + required this.onComplete, + }) : super(key: key); + + @override + _TableCellShortcutListenerState createState() => + _TableCellShortcutListenerState(); +} + +class _TableCellShortcutListenerState extends State { + List _shortcut = []; + + @override + void initState() { + _shortcut = widget.initShortcut.split('+'); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return RawKeyboardListener( + focusNode: FocusNode(), + onKey: (evt) { + evt.sout(); + }, + child: GestureDetector( + onTap: () {}, + child: Focus( + autofocus: true, + onKeyEvent: (_, __) => KeyEventResult.skipRemainingHandlers, + child: Container( + height: kMinInteractiveDimension * .86, + width: widget.width, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius), + color: Colors.grey.withOpacity(.3), + border: Border.all( + width: 2, + color: Focus.of(context).hasFocus + ? context.watch().activeColor ?? + Color(0xff565656) + : Color(0xff565656)), + ), + child: Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: EdgeInsets.only(left: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: _shortcut + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 2.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + defaultBorderRadius / 2), + color: context.t.dialogBackgroundColor, + border: Border.all( + width: 1, + color: Focus.of(context).hasFocus + ? context + .watch() + .activeColor ?? + Color(0xff565656) + : Color(0xff565656)), + ), + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 5.0), + child: Text( + e, + style: TextStyle( + color: context + .watch() + .activeColor, + ), + ), + ), + ), + ), + ) + .toList(), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/app/lib/widgets/table_cell_text_field.dart b/app/lib/widgets/table_cell_text_field.dart index 0e32bbd..3404173 100644 --- a/app/lib/widgets/table_cell_text_field.dart +++ b/app/lib/widgets/table_cell_text_field.dart @@ -20,7 +20,9 @@ class TableCellTextField extends StatefulWidget { } class _TableCellTextFieldState extends State { - final FocusNode _focusNode = FocusNode(); + final FocusNode _focusNode = FocusNode( + onKeyEvent: (_, __) => KeyEventResult.skipRemainingHandlers, + ); final TextEditingController _controller = TextEditingController(); @override From 930fd5ddf71836d357232df03074b60b70c64b9f Mon Sep 17 00:00:00 2001 From: debuggerx Date: Wed, 10 Nov 2021 18:40:51 +0800 Subject: [PATCH 13/16] wip: shortcut listener widget. --- app/lib/constants/constants.dart | 2 + app/lib/constants/keyboard_mapper.dart | 11 ++ app/lib/pages/gesture_editor.dart | 143 ++++++++++------------ app/lib/widgets/dde_button.dart | 5 +- app/lib/widgets/table_cell_shortcut_listener.dart | 70 +++++++---- app/resources/langs/en.json | 3 + app/resources/langs/zh-CN.json | 3 + 7 files changed, 131 insertions(+), 106 deletions(-) create mode 100644 app/lib/constants/keyboard_mapper.dart diff --git a/app/lib/constants/constants.dart b/app/lib/constants/constants.dart index dfee4a3..b57bd45 100644 --- a/app/lib/constants/constants.dart +++ b/app/lib/constants/constants.dart @@ -22,6 +22,8 @@ const double defaultButtonHeight = 36; const List builtInCommands = [ 'ShowWorkspace', + 'Handle4Or5FingersSwipeUp', + 'Handle4Or5FingersSwipeDown', 'ToggleMaximize', 'Minimize', 'ShowWindow', diff --git a/app/lib/constants/keyboard_mapper.dart b/app/lib/constants/keyboard_mapper.dart new file mode 100644 index 0000000..859f65a --- /dev/null +++ b/app/lib/constants/keyboard_mapper.dart @@ -0,0 +1,11 @@ +import 'package:flutter/services.dart'; + +/// https://github.com/linuxdeepin/dde-daemon/blob/76be73fbf019cee73983292e1edf47611ed9a219/gesture/manager.go#L386 +final Map keyMapper = { + LogicalKeyboardKey.control: 'ctrl', + LogicalKeyboardKey.controlLeft: 'ctrl', + LogicalKeyboardKey.controlRight: 'ctrl', + LogicalKeyboardKey.shift: 'shift', + LogicalKeyboardKey.shiftLeft: 'shift', + LogicalKeyboardKey.shiftRight: 'shift', +}; diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index e5d00ff..f9cf807 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -47,8 +47,7 @@ class GestureEditor extends StatelessWidget { visible: layoutProvider.localManagerOpened == false, child: DButton( width: defaultButtonHeight, - onTap: () => - H.openPanel(context, PanelType.local_manager), + onTap: () => H.openPanel(context, PanelType.local_manager), child: Icon( CupertinoIcons.square_list, ), @@ -77,14 +76,11 @@ class GestureEditor extends StatelessWidget { Expanded( child: GestureDetector( onTap: () { - context - .read() - .setProps(editMode: false); + context.read().setProps(editMode: false); }, child: Container( decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(defaultBorderRadius), + borderRadius: BorderRadius.circular(defaultBorderRadius), border: Border.all( width: .2, color: context.t.dividerColor, @@ -92,19 +88,16 @@ class GestureEditor extends StatelessWidget { ), width: double.infinity, clipBehavior: Clip.antiAlias, - child: LayoutBuilder(builder: - (BuildContext context, BoxConstraints constraints) { + child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { return AdaptiveScrollbar( controller: verticalCtrl, underColor: Colors.transparent, sliderDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.4), ), sliderActiveDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.6), ), position: ScrollbarPosition.right, @@ -114,13 +107,11 @@ class GestureEditor extends StatelessWidget { width: _scrollBarWidth, underColor: Colors.transparent, sliderDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.4), ), sliderActiveDecoration: BoxDecoration( - borderRadius: - BorderRadius.circular(_scrollBarWidth / 2), + borderRadius: BorderRadius.circular(_scrollBarWidth / 2), color: Colors.grey.withOpacity(.6), ), controller: horizontalCtrl, @@ -129,58 +120,28 @@ class GestureEditor extends StatelessWidget { scrollDirection: Axis.horizontal, controller: horizontalCtrl, child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: constraints.maxWidth), + constraints: BoxConstraints(minWidth: constraints.maxWidth), child: DDataTable( showBottomBorder: true, headingRowHeight: _headingRowHeight, showCheckboxColumn: true, - headerBackgroundColor: - context.t.dialogBackgroundColor, + headerBackgroundColor: context.t.dialogBackgroundColor, verticalScrollController: verticalCtrl, - dataRowColor: - MaterialStateProperty.resolveWith( - (Set states) { - if (states.contains(MaterialState.hovered)) - return context.t.dialogBackgroundColor; + dataRowColor: MaterialStateProperty.resolveWith((Set states) { + if (states.contains(MaterialState.hovered)) return context.t.dialogBackgroundColor; if (states.contains(MaterialState.selected)) - return context - .read() - .currentActiveColor; + return context.read().currentActiveColor; return null; }), columns: [ - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_fingers - .tr()), - center: true), - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_gesture - .tr()), - center: true), - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_direction - .tr()), - center: true), - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_type - .tr()), - center: true), - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_command - .tr())), - DDataColumn( - label: Text(LocaleKeys - .gesture_editor_remark - .tr())), + DDataColumn(label: Text(LocaleKeys.gesture_editor_fingers.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_gesture.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_direction.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_type.tr()), center: true), + DDataColumn(label: Text(LocaleKeys.gesture_editor_command.tr())), + DDataColumn(label: Text(LocaleKeys.gesture_editor_remark.tr())), ], - rows: _buildDataRows( - schemeProvider.gestures, context), + rows: _buildDataRows(schemeProvider.gestures, context), ), ), ), @@ -210,12 +171,9 @@ class GestureEditor extends StatelessWidget { } } -List _buildDataRows( - List? gestures, BuildContext context) => - (gestures ?? []).map((gesture) { +List _buildDataRows(List? gestures, BuildContext context) => (gestures ?? []).map((gesture) { var gesturePropProvider = context.watch(); - bool editing = gesturePropProvider == gesture && - gesturePropProvider.editMode == true; + bool editing = gesturePropProvider == gesture && gesturePropProvider.editMode == true; bool selected = gesturePropProvider == gesture && !editing; return DDataRow( onSelectChanged: (selected) { @@ -243,15 +201,11 @@ List _buildDataRows( } }, selected: selected, - cells: editing - ? _buildRowCellsEditing(context, gesture) - : _buildRowCellsNormal(context, selected, gesture), + cells: editing ? _buildRowCellsEditing(context, gesture) : _buildRowCellsNormal(context, selected, gesture), ); }).toList(); -List _buildRowCellsEditing( - BuildContext context, GestureProp gesture) => - [ +List _buildRowCellsEditing(BuildContext context, GestureProp gesture) => [ DButton.dropdown( enabled: true, child: DropdownButton( @@ -339,6 +293,7 @@ List _buildRowCellsEditing( value: context.watch().type, onChanged: (value) => context.read().setProps( type: value, + command: '', editMode: true, ), isExpanded: true, @@ -356,7 +311,6 @@ List _buildRowCellsEditing( ].map((e) => DDataCell(e)).toList(); Widget _buildCommandCellsEditing(BuildContext context) { - 'build cmd cell'.sout(); var gesture = context.read(); switch (gesture.type) { case GestureType.commandline: @@ -385,9 +339,7 @@ Widget _buildCommandCellsEditing(BuildContext context) { ), ) .toList(), - value: builtInCommands.contains(gesture.command) - ? gesture.command - : builtInCommands.first, + value: builtInCommands.contains(gesture.command) ? gesture.command : builtInCommands.first, onChanged: (value) => context.read().setProps( command: value, editMode: true, @@ -397,7 +349,7 @@ Widget _buildCommandCellsEditing(BuildContext context) { ); case GestureType.shortcut: return TableCellShortcutListener( - width: 150.0, + width: 250.0, initShortcut: gesture.command ?? '', onComplete: (value) => context.read().setProps( command: value, @@ -409,9 +361,7 @@ Widget _buildCommandCellsEditing(BuildContext context) { } } -List _buildRowCellsNormal( - BuildContext context, bool selected, GestureProp gesture) => - [ +List _buildRowCellsNormal(BuildContext context, bool selected, GestureProp gesture) => [ Center( child: Text( '${gesture.fingers}', @@ -430,9 +380,40 @@ List _buildRowCellsNormal( child: Text( '${LocaleKeys.gesture_editor_types}.${H.getGestureTypeName(gesture.type)}', ).tr()), - Text( - gesture.command ?? '', - ), + gesture.type == GestureType.shortcut + ? Row( + mainAxisAlignment: MainAxisAlignment.start, + children: (gesture.command ?? '') + .split('+') + .map( + (e) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 2.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius / 2), + color: context.t.dialogBackgroundColor, + border: Border.all( + width: 1, + color: Color(0xff565656), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + child: Text( + e.notNull ? e : LocaleKeys.str_null.tr(), + style: TextStyle( + color: context.watch().currentActiveColor, + ), + ), + ), + ), + ), + ) + .toList(), + ) + : Text( + gesture.command ?? '', + ), Text( gesture.remark ?? '', ), diff --git a/app/lib/widgets/dde_button.dart b/app/lib/widgets/dde_button.dart index ce54464..77a00d6 100644 --- a/app/lib/widgets/dde_button.dart +++ b/app/lib/widgets/dde_button.dart @@ -126,8 +126,9 @@ class _DButtonState extends State { begin: Alignment.topCenter, end: Alignment.bottomCenter, ), - borderColor: - _hovering ? widget.activeBorderColor ?? context.watch().activeColor : Color(0xff565656), + borderColor: _hovering + ? (widget.activeBorderColor ?? context.watch().currentActiveColor) + : Color(0xff565656), borderWidth: 2, borderRadius: BorderRadius.circular(defaultBorderRadius), child: MouseRegion( diff --git a/app/lib/widgets/table_cell_shortcut_listener.dart b/app/lib/widgets/table_cell_shortcut_listener.dart index fc8a963..b1f8282 100644 --- a/app/lib/widgets/table_cell_shortcut_listener.dart +++ b/app/lib/widgets/table_cell_shortcut_listener.dart @@ -1,7 +1,9 @@ import 'package:dde_gesture_manager/constants/constants.dart'; +import 'package:dde_gesture_manager/constants/keyboard_mapper.dart'; import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:flutter/material.dart'; import 'package:dde_gesture_manager/extensions.dart'; +import 'package:flutter/services.dart'; class TableCellShortcutListener extends StatefulWidget { final double width; @@ -16,28 +18,62 @@ class TableCellShortcutListener extends StatefulWidget { }) : super(key: key); @override - _TableCellShortcutListenerState createState() => - _TableCellShortcutListenerState(); + _TableCellShortcutListenerState createState() => _TableCellShortcutListenerState(); } class _TableCellShortcutListenerState extends State { List _shortcut = []; + bool inputMode = false; + FocusNode _focusNode = FocusNode(); + + _handleFocusChange() { + if (!_focusNode.hasFocus) { + widget.onComplete(_shortcut.join('+')); + } + } + + _tryToAddKey(LogicalKeyboardKey key) { + if (key.keyLabel.length == 1) key.keyLabel.sout(); + late String _key; + if (keyMapper.containsKey(key)) + _key = keyMapper[key]!; + else if (key.keyLabel.length == 1) _key = key.keyLabel.toLowerCase(); + + if (!_shortcut.contains(_key)) { + setState(() { + _shortcut.add(_key); + }); + } + } @override void initState() { _shortcut = widget.initShortcut.split('+'); + _focusNode.addListener(_handleFocusChange); super.initState(); } @override + void dispose() { + _focusNode.removeListener(_handleFocusChange); + super.dispose(); + } + + @override Widget build(BuildContext context) { return RawKeyboardListener( - focusNode: FocusNode(), + focusNode: _focusNode, onKey: (evt) { - evt.sout(); + RawKeyboard.instance.keysPressed.forEach(_tryToAddKey); + RawKeyboard.instance.keysPressed.sout(); }, child: GestureDetector( - onTap: () {}, + onTap: () { + setState(() { + _shortcut = []; + inputMode = true; + }); + }, child: Focus( autofocus: true, onKeyEvent: (_, __) => KeyEventResult.skipRemainingHandlers, @@ -50,8 +86,7 @@ class _TableCellShortcutListenerState extends State { border: Border.all( width: 2, color: Focus.of(context).hasFocus - ? context.watch().activeColor ?? - Color(0xff565656) + ? context.watch().activeColor ?? Color(0xff565656) : Color(0xff565656)), ), child: Align( @@ -66,27 +101,16 @@ class _TableCellShortcutListenerState extends State { padding: const EdgeInsets.symmetric(horizontal: 2.0), child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - defaultBorderRadius / 2), + borderRadius: BorderRadius.circular(defaultBorderRadius / 2), color: context.t.dialogBackgroundColor, - border: Border.all( - width: 1, - color: Focus.of(context).hasFocus - ? context - .watch() - .activeColor ?? - Color(0xff565656) - : Color(0xff565656)), + border: Border.all(width: 1, color: Color(0xff565656)), ), child: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 5.0), + padding: const EdgeInsets.symmetric(horizontal: 5.0), child: Text( - e, + e.notNull ? e : LocaleKeys.str_null.tr(), style: TextStyle( - color: context - .watch() - .activeColor, + color: context.watch().activeColor, ), ), ), diff --git a/app/resources/langs/en.json b/app/resources/langs/en.json index 7c1a22a..1e35fb9 100644 --- a/app/resources/langs/en.json +++ b/app/resources/langs/en.json @@ -62,5 +62,8 @@ "delete": "delete", "duplicate": "duplicate", "apply": "apply" + }, + "str": { + "null": "Null" } } \ No newline at end of file diff --git a/app/resources/langs/zh-CN.json b/app/resources/langs/zh-CN.json index 12c8ed0..e11ad41 100644 --- a/app/resources/langs/zh-CN.json +++ b/app/resources/langs/zh-CN.json @@ -62,5 +62,8 @@ "delete": "删除", "duplicate": "复制", "apply": "应用" + }, + "str": { + "null": "无" } } \ No newline at end of file From 64a73492490df49981dff4f6abb097cb25dc617b Mon Sep 17 00:00:00 2001 From: debuggerx Date: Fri, 12 Nov 2021 14:27:10 +0800 Subject: [PATCH 14/16] feat: shortcut keycode map completed. --- app/lib/constants/keyboard_mapper.dart | 11 - app/lib/pages/gesture_editor.dart | 45 +-- app/lib/utils/keyboard_mapper.dart | 405 ++++++++++++++++++++++ app/lib/widgets/table_cell_shortcut_listener.dart | 34 +- 4 files changed, 445 insertions(+), 50 deletions(-) delete mode 100644 app/lib/constants/keyboard_mapper.dart create mode 100644 app/lib/utils/keyboard_mapper.dart diff --git a/app/lib/constants/keyboard_mapper.dart b/app/lib/constants/keyboard_mapper.dart deleted file mode 100644 index 859f65a..0000000 --- a/app/lib/constants/keyboard_mapper.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/services.dart'; - -/// https://github.com/linuxdeepin/dde-daemon/blob/76be73fbf019cee73983292e1edf47611ed9a219/gesture/manager.go#L386 -final Map keyMapper = { - LogicalKeyboardKey.control: 'ctrl', - LogicalKeyboardKey.controlLeft: 'ctrl', - LogicalKeyboardKey.controlRight: 'ctrl', - LogicalKeyboardKey.shift: 'shift', - LogicalKeyboardKey.shiftLeft: 'shift', - LogicalKeyboardKey.shiftRight: 'shift', -}; diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index f9cf807..d3ca21b 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -6,6 +6,7 @@ import 'package:dde_gesture_manager/models/scheme.dart'; import 'package:dde_gesture_manager/models/scheme.provider.dart'; import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; +import 'package:dde_gesture_manager/utils/keyboard_mapper.dart'; import 'package:dde_gesture_manager/widgets/dde_button.dart'; import 'package:dde_gesture_manager/widgets/dde_data_table.dart'; import 'package:dde_gesture_manager/widgets/table_cell_shortcut_listener.dart'; @@ -383,33 +384,33 @@ List _buildRowCellsNormal(BuildContext context, bool selected, Gestur gesture.type == GestureType.shortcut ? Row( mainAxisAlignment: MainAxisAlignment.start, - children: (gesture.command ?? '') - .split('+') - .map( - (e) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 2.0), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(defaultBorderRadius / 2), - color: context.t.dialogBackgroundColor, - border: Border.all( - width: 1, - color: Color(0xff565656), - ), + children: (gesture.command ?? '').split('+').map( + (e) { + var keyNames = getPhysicalKeyNamesByRealName(e); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 2.0), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(defaultBorderRadius / 2), + color: context.t.dialogBackgroundColor, + border: Border.all( + width: 1, + color: Color(0xff565656), ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 5.0), - child: Text( - e.notNull ? e : LocaleKeys.str_null.tr(), - style: TextStyle( - color: context.watch().currentActiveColor, - ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + child: Text( + keyNames != null ? keyNames.displayName : LocaleKeys.str_null.tr(), + style: TextStyle( + color: context.watch().currentActiveColor, ), ), ), ), - ) - .toList(), + ); + }, + ).toList(), ) : Text( gesture.command ?? '', diff --git a/app/lib/utils/keyboard_mapper.dart b/app/lib/utils/keyboard_mapper.dart new file mode 100644 index 0000000..b685232 --- /dev/null +++ b/app/lib/utils/keyboard_mapper.dart @@ -0,0 +1,405 @@ +import 'package:collection/collection.dart'; + +const KeysOrder = [ + 'Ctrl', + 'Super', + 'Alt', + 'Shift', + 'Return', + 'Escape', + 'BackSpace', + 'Tab', + 'space', + '→', + '←', + '↓', + '↑', + 'Print', + 'ScrollLock', + 'Pause', + 'Insert', + 'Home', + 'Page_Up', + 'Delete', + 'End', + 'Page_Down', + 'F1', + 'F2', + 'F3', + 'F4', + 'F5', + 'F6', + 'F7', + 'F8', + 'F9', + 'F10', + 'F11', + 'F12', + '-', + '=', + '(', + ')', + r'\', + ';', + "'", + '`', + ',', + '.', + '/', + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', +]; + +class KeyNames implements Comparable { + final String displayName; + final String realName; + + const KeyNames({required this.displayName, required this.realName}); + + @override + int compareTo(other) => KeysOrder.indexOf(this.displayName) - KeysOrder.indexOf(other.displayName); + + @override + String toString() => realName; +} + +KeyNames? getPhysicalKeyNames(int keyId) => _knownPhysicalKeyNames[keyId]; + +KeyNames? getPhysicalKeyNamesByRealName(String name) => + _knownPhysicalKeyNames.values.firstWhereOrNull((element) => element.realName == name); + +/// https://www.w3.org/TR/uievents-code/ +const Map _knownPhysicalKeyNames = { + /// https://www.w3.org/TR/uievents-code/#key-legacy + /*0x00000010: hyper, + 0x00000011: superKey, + 0x00000016: turbo, + 0x0007009b: abort, + 0x00000015: resume, + 0x00000014: suspend, + 0x00070079: again, + 0x0007007c: copy, + 0x0007007b: cut, + 0x0007007e: find, + 0x00070074: open, + 0x0007007d: paste, + 0x000700a3: props, + 0x00070077: select, + 0x0007007a: undo,*/ + + /// Often handled in hardware so that events aren't generated for this key. + /*0x00000012: fn, + 0x00000013: fnLock,*/ + + /// W.T.F + /*0x00000017: privacyScreenToggle, + 0x00010082: sleep, + 0x00010083: wakeUp, + 0x000100b5: displayToggleIntExt, + 0x0005ff01: gameButton1, + 0x0005ff02: gameButton2, + 0x0005ff03: gameButton3, + 0x0005ff04: gameButton4, + 0x0005ff05: gameButton5, + 0x0005ff06: gameButton6, + 0x0005ff07: gameButton7, + 0x0005ff08: gameButton8, + 0x0005ff09: gameButton9, + 0x0005ff0a: gameButton10, + 0x0005ff0b: gameButton11, + 0x0005ff0c: gameButton12, + 0x0005ff0d: gameButton13, + 0x0005ff0e: gameButton14, + 0x0005ff0f: gameButton15, + 0x0005ff10: gameButton16, + 0x0005ff11: gameButtonA, + 0x0005ff12: gameButtonB, + 0x0005ff13: gameButtonC, + 0x0005ff14: gameButtonLeft1, + 0x0005ff15: gameButtonLeft2, + 0x0005ff16: gameButtonMode, + 0x0005ff17: gameButtonRight1, + 0x0005ff18: gameButtonRight2, + 0x0005ff19: gameButtonSelect, + 0x0005ff1a: gameButtonStart, + 0x0005ff1b: gameButtonThumbLeft, + 0x0005ff1c: gameButtonThumbRight, + 0x0005ff1d: gameButtonX, + 0x0005ff1e: gameButtonY, + 0x0005ff1f: gameButtonZ, + 0x00070000: usbReserved, + 0x00070001: usbErrorRollOver, + 0x00070002: usbPostFail, + 0x00070003: usbErrorUndefined,*/ + + 0x00070004: const KeyNames(displayName: 'A', realName: 'a'), + 0x00070005: const KeyNames(displayName: 'B', realName: 'b'), + 0x00070006: const KeyNames(displayName: 'C', realName: 'c'), + 0x00070007: const KeyNames(displayName: 'D', realName: 'd'), + 0x00070008: const KeyNames(displayName: 'E', realName: 'e'), + 0x00070009: const KeyNames(displayName: 'F', realName: 'f'), + 0x0007000a: const KeyNames(displayName: 'G', realName: 'g'), + 0x0007000b: const KeyNames(displayName: 'H', realName: 'h'), + 0x0007000c: const KeyNames(displayName: 'I', realName: 'i'), + 0x0007000d: const KeyNames(displayName: 'J', realName: 'j'), + 0x0007000e: const KeyNames(displayName: 'K', realName: 'k'), + 0x0007000f: const KeyNames(displayName: 'L', realName: 'l'), + 0x00070010: const KeyNames(displayName: 'M', realName: 'm'), + 0x00070011: const KeyNames(displayName: 'N', realName: 'n'), + 0x00070012: const KeyNames(displayName: 'O', realName: 'o'), + 0x00070013: const KeyNames(displayName: 'P', realName: 'p'), + 0x00070014: const KeyNames(displayName: 'Q', realName: 'q'), + 0x00070015: const KeyNames(displayName: 'R', realName: 'r'), + 0x00070016: const KeyNames(displayName: 'S', realName: 's'), + 0x00070017: const KeyNames(displayName: 'T', realName: 't'), + 0x00070018: const KeyNames(displayName: 'U', realName: 'u'), + 0x00070019: const KeyNames(displayName: 'V', realName: 'v'), + 0x0007001a: const KeyNames(displayName: 'W', realName: 'w'), + 0x0007001b: const KeyNames(displayName: 'X', realName: 'x'), + 0x0007001c: const KeyNames(displayName: 'Y', realName: 'y'), + 0x0007001d: const KeyNames(displayName: 'Z', realName: 'z'), + 0x0007001e: const KeyNames(displayName: '1', realName: '1'), + 0x0007001f: const KeyNames(displayName: '2', realName: '2'), + 0x00070020: const KeyNames(displayName: '3', realName: '3'), + 0x00070021: const KeyNames(displayName: '4', realName: '4'), + 0x00070022: const KeyNames(displayName: '5', realName: '5'), + 0x00070023: const KeyNames(displayName: '6', realName: '6'), + 0x00070024: const KeyNames(displayName: '7', realName: '7'), + 0x00070025: const KeyNames(displayName: '8', realName: '8'), + 0x00070026: const KeyNames(displayName: '9', realName: '9'), + 0x00070027: const KeyNames(displayName: '0', realName: '0'), + 0x00070028: const KeyNames(displayName: 'Return', realName: 'Return'), + 0x00070029: const KeyNames(displayName: 'Escape', realName: 'Escape'), + 0x0007002a: const KeyNames(displayName: 'BackSpace', realName: 'BackSpace'), + 0x0007002b: const KeyNames(displayName: 'Tab', realName: 'Tab'), + 0x0007002c: const KeyNames(displayName: 'space', realName: 'space'), + 0x0007002d: const KeyNames(displayName: '-', realName: 'minus'), + 0x0007002e: const KeyNames(displayName: '=', realName: 'equal'), + 0x0007002f: const KeyNames(displayName: '(', realName: 'parenleft'), + 0x00070030: const KeyNames(displayName: ')', realName: 'parenright'), + 0x00070031: const KeyNames(displayName: r'\', realName: 'backslash'), + 0x00070033: const KeyNames(displayName: ';', realName: 'semicolon'), + 0x00070034: const KeyNames(displayName: "'", realName: 'apostrophe'), + 0x00070035: const KeyNames(displayName: '`', realName: 'grave'), + 0x00070036: const KeyNames(displayName: ',', realName: 'comma'), + 0x00070037: const KeyNames(displayName: '.', realName: 'period'), + 0x00070038: const KeyNames(displayName: '/', realName: 'slash'), + 0x00070039: const KeyNames(displayName: 'CapsLock', realName: 'Caps_Lock'), + 0x0007003a: const KeyNames(displayName: 'F1', realName: 'F1'), + 0x0007003b: const KeyNames(displayName: 'F2', realName: 'F2'), + 0x0007003c: const KeyNames(displayName: 'F3', realName: 'F3'), + 0x0007003d: const KeyNames(displayName: 'F4', realName: 'F4'), + 0x0007003e: const KeyNames(displayName: 'F5', realName: 'F5'), + 0x0007003f: const KeyNames(displayName: 'F6', realName: 'F6'), + 0x00070040: const KeyNames(displayName: 'F7', realName: 'F7'), + 0x00070041: const KeyNames(displayName: 'F8', realName: 'F8'), + 0x00070042: const KeyNames(displayName: 'F9', realName: 'F9'), + 0x00070043: const KeyNames(displayName: 'F10', realName: 'F10'), + 0x00070044: const KeyNames(displayName: 'F11', realName: 'F11'), + 0x00070045: const KeyNames(displayName: 'F12', realName: 'F12'), + 0x00070046: const KeyNames(displayName: 'Print', realName: 'Print'), + 0x00070047: const KeyNames(displayName: 'ScrollLock', realName: 'Scroll_Lock'), + 0x00070048: const KeyNames(displayName: 'Pause', realName: 'Pause'), + 0x00070049: const KeyNames(displayName: 'Insert', realName: 'Insert'), + 0x0007004a: const KeyNames(displayName: 'Home', realName: 'Home'), + 0x0007004b: const KeyNames(displayName: 'Page_Up', realName: 'Page_Up'), + 0x0007004c: const KeyNames(displayName: 'Delete', realName: 'Delete'), + 0x0007004d: const KeyNames(displayName: 'End', realName: 'End'), + 0x0007004e: const KeyNames(displayName: 'Page_Down', realName: 'Page_Down'), + 0x0007004f: const KeyNames(displayName: '→', realName: 'Right'), + 0x00070050: const KeyNames(displayName: '←', realName: 'Left'), + 0x00070051: const KeyNames(displayName: '↓', realName: 'Down'), + 0x00070052: const KeyNames(displayName: '↑', realName: 'Up'), + 0x00070053: const KeyNames(displayName: 'NumLock', realName: 'Num_Lock'), + 0x00070054: const KeyNames(displayName: 'KP_Divide', realName: 'KP_Divide'), + 0x00070055: const KeyNames(displayName: 'KP_Multiply', realName: 'KP_Multiply'), + 0x00070056: const KeyNames(displayName: 'KP_Subtract', realName: 'KP_Subtract'), + 0x00070057: const KeyNames(displayName: 'KP_Add', realName: 'KP_Add'), + 0x00070058: const KeyNames(displayName: 'KP_Enter', realName: 'KP_Enter'), + 0x00070059: const KeyNames(displayName: 'KP_1', realName: 'KP_1'), + 0x0007005a: const KeyNames(displayName: 'KP_2', realName: 'KP_2'), + 0x0007005b: const KeyNames(displayName: 'KP_3', realName: 'KP_3'), + 0x0007005c: const KeyNames(displayName: 'KP_4', realName: 'KP_4'), + 0x0007005d: const KeyNames(displayName: 'KP_5', realName: 'KP_5'), + 0x0007005e: const KeyNames(displayName: 'KP_6', realName: 'KP_6'), + 0x0007005f: const KeyNames(displayName: 'KP_7', realName: 'KP_7'), + 0x00070060: const KeyNames(displayName: 'KP_8', realName: 'KP_8'), + 0x00070061: const KeyNames(displayName: 'KP_9', realName: 'KP_9'), + 0x00070062: const KeyNames(displayName: 'KP_0', realName: 'KP_0'), + 0x00070063: const KeyNames(displayName: '.', realName: 'KP_Decimal'), + + /// IntlBackslash ??? + 0x00070064: const KeyNames(displayName: r'\', realName: 'backslash'), + 0x00070065: const KeyNames(displayName: 'Menu', realName: 'Menu'), + + /// Mac only + // 0x00070066: power, + 0x00070067: const KeyNames(displayName: 'KP_Equal', realName: 'KP_Equal'), + 0x00070068: const KeyNames(displayName: 'F13', realName: 'F13'), + 0x00070069: const KeyNames(displayName: 'F14', realName: 'F14'), + 0x0007006a: const KeyNames(displayName: 'F15', realName: 'F15'), + 0x0007006b: const KeyNames(displayName: 'F16', realName: 'F16'), + 0x0007006c: const KeyNames(displayName: 'F17', realName: 'F17'), + 0x0007006d: const KeyNames(displayName: 'F18', realName: 'F18'), + 0x0007006e: const KeyNames(displayName: 'F19', realName: 'F19'), + 0x0007006f: const KeyNames(displayName: 'F20', realName: 'F20'), + 0x00070070: const KeyNames(displayName: 'F21', realName: 'F21'), + 0x00070071: const KeyNames(displayName: 'F22', realName: 'F22'), + 0x00070072: const KeyNames(displayName: 'F23', realName: 'F23'), + 0x00070073: const KeyNames(displayName: 'F24', realName: 'F24'), + + /// Not present on standard PC keyboards. + // 0x00070075: help, + 0x0007007f: const KeyNames(displayName: 'XF86AudioMute', realName: 'XF86AudioMute'), + 0x00070080: const KeyNames(displayName: 'XF86AudioRaiseVolume', realName: 'XF86AudioRaiseVolume'), + 0x00070081: const KeyNames(displayName: 'XF86AudioLowerVolume', realName: 'XF86AudioLowerVolume'), + 0x00070085: const KeyNames(displayName: 'KP_Separator', realName: 'KP_Separator'), + 0x00070087: const KeyNames(displayName: 'KanaRo', realName: 'kana_RO'), + 0x00070088: const KeyNames(displayName: 'Hiragana_Katakana', realName: 'Hiragana_Katakana'), + 0x00070089: const KeyNames(displayName: 'yen', realName: 'yen'), + 0x0007008a: const KeyNames(displayName: 'Henkan_Mode', realName: 'Henkan_Mode'), + 0x0007008b: const KeyNames(displayName: 'Muhenkan', realName: 'Muhenkan'), + 0x00070090: const KeyNames(displayName: 'Hangul', realName: 'Hangul'), + 0x00070091: const KeyNames(displayName: 'Hangul_Hanja', realName: 'Hangul_Hanja'), + 0x00070092: const KeyNames(displayName: 'Katakana', realName: 'Katakana'), + 0x00070093: const KeyNames(displayName: 'Hiragana', realName: 'Hiragana'), + 0x00070094: const KeyNames(displayName: 'Zenkaku', realName: 'Zenkaku'), + 0x000700b6: const KeyNames(displayName: 'KP_Left', realName: 'KP_Left'), + 0x000700b7: const KeyNames(displayName: 'KP_Right', realName: 'KP_Right'), + + /// Found on the Microsoft Natural Keyboard. + // 0x000700bb: numpadBackspace, + + /// W.T.F ??? + /*0x000700d0: numpadMemoryStore, + 0x000700d1: numpadMemoryRecall, + 0x000700d2: numpadMemoryClear, + 0x000700d3: numpadMemoryAdd, + 0x000700d4: numpadMemorySubtract, + 0x000700d7: numpadSignChange, + 0x000700d9: numpadClearEntry,*/ + 0x000700d8: const KeyNames(displayName: 'NumLock', realName: 'Num_Lock'), + 0x000700e0: const KeyNames(displayName: 'Ctrl', realName: 'Control_L'), + 0x000700e1: const KeyNames(displayName: 'Shift', realName: 'Shift_L'), + 0x000700e2: const KeyNames(displayName: 'Alt', realName: 'Alt_L'), + 0x000700e3: const KeyNames(displayName: 'Super', realName: 'Super_L'), + 0x000700e4: const KeyNames(displayName: 'Ctrl', realName: 'Control_R'), + 0x000700e5: const KeyNames(displayName: 'Shift', realName: 'Shift_R'), + 0x000700e6: const KeyNames(displayName: 'Alt', realName: 'Alt_R'), + 0x000700e7: const KeyNames(displayName: 'Super', realName: 'Super_R'), + + /// Toggles the display of information about the currently selected content, program, or media. + // 0x000c0060: info, + + /// Toggles closed captioning on and off. + // 0x000c0061: closedCaptionToggle, + + /// Too dangerous ... + /*0x000c006f: brightnessUp, + 0x000c0070: brightnessDown, + 0x000c0072: brightnessToggle, + 0x000c0073: brightnessMinimum, + 0x000c0074: brightnessMaximum, + 0x000c0075: brightnessAuto,*/ + + /// seems only works on mobile. + /*0x000c0079: kbdIllumUp, + 0x000c007a: kbdIllumDown, + 0x000c0083: mediaLast, + 0x000c008c: launchPhone, + 0x000c008d: programGuide, + 0x000c0094: exit, + 0x000c009c: channelUp, + 0x000c009d: channelDown, + 0x000c00b0: mediaPlay, + 0x000c00b1: mediaPause, + 0x000c00b2: mediaRecord, + 0x000c00b3: mediaFastForward, + 0x000c00b4: mediaRewind, + 0x000c00b5: mediaTrackNext, + 0x000c00b6: mediaTrackPrevious, + 0x000c00b7: mediaStop, + + /// Mac only + // 0x000c00b8: eject, + 0x000c00cd: mediaPlayPause, + 0x000c00cf: speechInputToggle, + 0x000c00e5: bassBoost, + 0x000c0183: mediaSelect,*/ + 0x000c0184: const KeyNames(displayName: 'XF86Word', realName: 'XF86Word'), + 0x000c0186: const KeyNames(displayName: 'XF86Excel', realName: 'XF86Excel'), + 0x000c018a: const KeyNames(displayName: 'XF86Mail', realName: 'XF86Mail'), + + /// not implements on linux. + // 0x000c018d: launchContacts, + 0x000c018e: const KeyNames(displayName: 'XF86Calendar', realName: 'XF86Calendar'), + 0x000c0192: const KeyNames(displayName: 'XF86Launch2', realName: 'XF86Launch2'), + 0x000c0194: const KeyNames(displayName: 'XF86Launch1', realName: 'XF86Launch1'), + + /// I don't think need implement those keys + /*0x000c0196: launchInternetBrowser, + 0x000c019c: logOff, + 0x000c019e: lockScreen, + 0x000c019f: launchControlPanel, + 0x000c01a2: selectTask, + 0x000c01a7: launchDocuments, + 0x000c01ab: spellCheck, + 0x000c01ae: launchKeyboardLayout, + 0x000c01b1: launchScreenSaver, + 0x000c01b7: launchAudioBrowser, + 0x000c01cb: launchAssistant, + 0x000c0201: newKey, + 0x000c0203: close, + 0x000c0207: save, + 0x000c0208: print, + 0x000c0221: browserSearch, + 0x000c0223: browserHome, + 0x000c0224: browserBack, + 0x000c0225: browserForward, + 0x000c0226: browserStop, + 0x000c0227: browserRefresh, + 0x000c022a: browserFavorites, + 0x000c022d: zoomIn, + 0x000c022e: zoomOut, + 0x000c0232: zoomToggle, + 0x000c0279: redo, + 0x000c0289: mailReply, + 0x000c028b: mailForward, + 0x000c028c: mailSend, + 0x000c029d: keyboardLayoutSelect, + 0x000c029f: showAllWindows,*/ +}; diff --git a/app/lib/widgets/table_cell_shortcut_listener.dart b/app/lib/widgets/table_cell_shortcut_listener.dart index b1f8282..e99ec25 100644 --- a/app/lib/widgets/table_cell_shortcut_listener.dart +++ b/app/lib/widgets/table_cell_shortcut_listener.dart @@ -1,8 +1,8 @@ import 'package:dde_gesture_manager/constants/constants.dart'; -import 'package:dde_gesture_manager/constants/keyboard_mapper.dart'; +import 'package:dde_gesture_manager/extensions.dart'; import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:dde_gesture_manager/utils/keyboard_mapper.dart'; import 'package:flutter/material.dart'; -import 'package:dde_gesture_manager/extensions.dart'; import 'package:flutter/services.dart'; class TableCellShortcutListener extends StatefulWidget { @@ -22,7 +22,7 @@ class TableCellShortcutListener extends StatefulWidget { } class _TableCellShortcutListenerState extends State { - List _shortcut = []; + List _shortcut = []; bool inputMode = false; FocusNode _focusNode = FocusNode(); @@ -32,23 +32,23 @@ class _TableCellShortcutListenerState extends State { } } - _tryToAddKey(LogicalKeyboardKey key) { - if (key.keyLabel.length == 1) key.keyLabel.sout(); - late String _key; - if (keyMapper.containsKey(key)) - _key = keyMapper[key]!; - else if (key.keyLabel.length == 1) _key = key.keyLabel.toLowerCase(); - - if (!_shortcut.contains(_key)) { + _tryToAddKey(PhysicalKeyboardKey key) { + var names = getPhysicalKeyNames(key.usbHidUsage); + if (names != null && !_shortcut.contains(names)) setState(() { - _shortcut.add(_key); + _shortcut.add(names); + _shortcut.sort(); }); - } } @override void initState() { - _shortcut = widget.initShortcut.split('+'); + var __shortcut = widget.initShortcut.split('+'); + __shortcut.forEach((name) { + var keyNames = getPhysicalKeyNamesByRealName(name); + if (keyNames != null) _shortcut.add(keyNames); + }); + _shortcut.sort(); _focusNode.addListener(_handleFocusChange); super.initState(); } @@ -64,8 +64,8 @@ class _TableCellShortcutListenerState extends State { return RawKeyboardListener( focusNode: _focusNode, onKey: (evt) { - RawKeyboard.instance.keysPressed.forEach(_tryToAddKey); - RawKeyboard.instance.keysPressed.sout(); + evt.physicalKey.sout(); + _tryToAddKey(evt.physicalKey); }, child: GestureDetector( onTap: () { @@ -108,7 +108,7 @@ class _TableCellShortcutListenerState extends State { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 5.0), child: Text( - e.notNull ? e : LocaleKeys.str_null.tr(), + e.displayName.notNull ? e.displayName : LocaleKeys.str_null.tr(), style: TextStyle( color: context.watch().activeColor, ), From 91fbb84faa41be588e4e6724064d1fe4095a9d31 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Fri, 12 Nov 2021 14:27:42 +0800 Subject: [PATCH 15/16] feat: shortcut keycode map completed. --- app/lib/widgets/table_cell_shortcut_listener.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/app/lib/widgets/table_cell_shortcut_listener.dart b/app/lib/widgets/table_cell_shortcut_listener.dart index e99ec25..7d6e1fe 100644 --- a/app/lib/widgets/table_cell_shortcut_listener.dart +++ b/app/lib/widgets/table_cell_shortcut_listener.dart @@ -64,7 +64,6 @@ class _TableCellShortcutListenerState extends State { return RawKeyboardListener( focusNode: _focusNode, onKey: (evt) { - evt.physicalKey.sout(); _tryToAddKey(evt.physicalKey); }, child: GestureDetector( From 1c6d50a4b6b8271df63f740b6b0482b2011cbcd2 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Fri, 12 Nov 2021 15:06:22 +0800 Subject: [PATCH 16/16] feat: make built_in commands support i18n. --- app/lib/pages/gesture_editor.dart | 8 +++++--- app/resources/langs/en.json | 16 ++++++++++++++++ app/resources/langs/zh-CN.json | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/app/lib/pages/gesture_editor.dart b/app/lib/pages/gesture_editor.dart index d3ca21b..868d8b4 100644 --- a/app/lib/pages/gesture_editor.dart +++ b/app/lib/pages/gesture_editor.dart @@ -333,14 +333,16 @@ Widget _buildCommandCellsEditing(BuildContext context) { .map( (e) => DropdownMenuItem( child: Text( - e, + ('${LocaleKeys.built_in_commands}.$e').tr(), textScaleFactor: .8, ), - value: e, + value: ('${LocaleKeys.built_in_commands}.$e').tr(), ), ) .toList(), - value: builtInCommands.contains(gesture.command) ? gesture.command : builtInCommands.first, + value: + ('${LocaleKeys.built_in_commands}.${(builtInCommands.contains(gesture.command) ? gesture.command : builtInCommands.first)!}') + .tr(), onChanged: (value) => context.read().setProps( command: value, editMode: true, diff --git a/app/resources/langs/en.json b/app/resources/langs/en.json index 1e35fb9..9790aad 100644 --- a/app/resources/langs/en.json +++ b/app/resources/langs/en.json @@ -65,5 +65,21 @@ }, "str": { "null": "Null" + }, + "built_in_commands": { + "ShowWorkspace": "ShowWorkspace", + "Handle4Or5FingersSwipeUp": "4/5FingersSwipeUp", + "Handle4Or5FingersSwipeDown": "4/5FingersSwipeDown", + "ToggleMaximize": "ToggleMaximize", + "Minimize": "Minimize", + "ShowWindow": "ShowWindow", + "ShowAllWindow": "ShowAllWindow", + "SwitchApplication": "SwitchApplication", + "ReverseSwitchApplication": "ReverseSwitchApplication", + "SwitchWorkspace": "SwitchWorkspace", + "ReverseSwitchWorkspace": "ReverseSwitchWorkspace", + "SplitWindowLeft": "SplitWindowLeft", + "SplitWindowRight": "SplitWindowRight", + "MoveWindow": "MoveWindow" } } \ No newline at end of file diff --git a/app/resources/langs/zh-CN.json b/app/resources/langs/zh-CN.json index e11ad41..2883e08 100644 --- a/app/resources/langs/zh-CN.json +++ b/app/resources/langs/zh-CN.json @@ -65,5 +65,21 @@ }, "str": { "null": "无" + }, + "built_in_commands": { + "ShowWorkspace": "显示工作区", + "Handle4Or5FingersSwipeUp": "4/5指向上划", + "Handle4Or5FingersSwipeDown": "4/5指向下划", + "ToggleMaximize": "全屏切换", + "Minimize": "最小化", + "ShowWindow": "显示桌面", + "ShowAllWindow": "查看所有窗口", + "SwitchApplication": "切换应用窗口", + "ReverseSwitchApplication": "反向切换应用窗口", + "SwitchWorkspace": "切换工作区", + "ReverseSwitchWorkspace": "反向切换工作区", + "SplitWindowLeft": "向左分屏", + "SplitWindowRight": "向右分屏", + "MoveWindow": "移动窗口" } } \ No newline at end of file