From 9f47dbc791cc6d5ae4057a3d16d0967e3304788d Mon Sep 17 00:00:00 2001 From: debuggerx Date: Thu, 16 Sep 2021 18:45:59 +0800 Subject: [PATCH 1/7] wip --- app/lib/main.dart | 62 ++++++++++++++++++++++++++++++-------------- app/lib/models/settings.dart | 31 ++++++++++++++++++++++ app/lib/utils/helper.dart | 2 ++ app/pubspec.yaml | 1 + 4 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 app/lib/models/settings.dart create mode 100644 app/lib/utils/helper.dart diff --git a/app/lib/main.dart b/app/lib/main.dart index 576db6d..a886f37 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,6 +1,9 @@ +import 'package:dde_gesture_manager/models/settings.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:gsettings/gsettings.dart'; +import 'package:provider/provider.dart'; import 'package:window_manager/window_manager.dart'; import 'package:xdg_directories/xdg_directories.dart' as xdgDir; @@ -20,32 +23,51 @@ Future main() async { var windowManager = WindowManager.instance; windowManager.setTitle('Gesture Manager For DDE'); windowManager.setMinimumSize(const Size(800, 600)); - var xsettings = GSettings('com.deepin.xsettings'); - // xsettings.get('scale-factor').then((value) { - // print(value.toString()); - // }); - xsettings.get('theme-name').then((value) { - print(value.toString()); - }); - xsettings.keysChanged.listen((event) { - xsettings.get('theme-name').then((value) { - print(value.toString()); - }); - }); } runApp(MyApp()); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + var xsettings = GSettings('com.deepin.xsettings'); + + @override + void initState() { + super.initState(); + WidgetsBinding.instance?.addPostFrameCallback((_) { + xsettings.keysChanged.listen((event) { + xsettings.get('theme-name').then((value) { + context.read().setProps(isDarkMode: value.toString().contains('dark')); + }); + }); + }); + } + @override Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); + return MultiProvider( + providers: [ + Provider(create: (context) => SettingsProvider()), + ], + builder: (context, child) { + var isDarkMode = context.watch().settings.isDarkMode; + return isDarkMode == null + ? Center( + child: CircularProgressIndicator(), + ) + : MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: isDarkMode ? Colors.blue : Colors.blue, + brightness: isDarkMode ? Brightness.dark : Brightness.light, + ), + home: MyHomePage(title: 'Flutter Demo Home Page'), + ); + }); } } diff --git a/app/lib/models/settings.dart b/app/lib/models/settings.dart new file mode 100644 index 0000000..60de8f8 --- /dev/null +++ b/app/lib/models/settings.dart @@ -0,0 +1,31 @@ +import 'package:flutter/foundation.dart'; + +class Settings { + Settings({ + this.isDarkMode, + }); + + bool? isDarkMode; +} + +class SettingsProvider extends ChangeNotifier { + Settings _settings = Settings(); + + Settings get settings => _settings; + + set settings(Settings newSettings) { + _settings = newSettings; + notifyListeners(); + } + + void setProps({ + bool? isDarkMode, + }) { + bool changed = false; + if (isDarkMode != _settings.isDarkMode) { + _settings.isDarkMode = isDarkMode; + changed = true; + } + if (changed) notifyListeners(); + } +} diff --git a/app/lib/utils/helper.dart b/app/lib/utils/helper.dart new file mode 100644 index 0000000..682c2c1 --- /dev/null +++ b/app/lib/utils/helper.dart @@ -0,0 +1,2 @@ +class H { +} \ No newline at end of file diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 9bb02d5..446340f 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: shared_preferences: ^2.0.7 xdg_directories: 0.2.0 gsettings: 0.2.0 + provider: ^6.0.0 window_size: path: 3rd_party/window_size xdg_directories_web: -- 2.11.0 From 1efc737284b9ec29285601e10043b66312af2230 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Fri, 17 Sep 2021 18:23:22 +0800 Subject: [PATCH 2/7] wip: fix --- app/lib/main.dart | 82 ++++++++++++++++++++++++-------------------- app/lib/models/settings.dart | 21 +++--------- 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/app/lib/main.dart b/app/lib/main.dart index a886f37..1318877 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -27,47 +27,53 @@ Future main() async { runApp(MyApp()); } -class MyApp extends StatefulWidget { - @override - State createState() => _MyAppState(); -} - -class _MyAppState extends State { - var xsettings = GSettings('com.deepin.xsettings'); - - @override - void initState() { - super.initState(); - WidgetsBinding.instance?.addPostFrameCallback((_) { - xsettings.keysChanged.listen((event) { - xsettings.get('theme-name').then((value) { - context.read().setProps(isDarkMode: value.toString().contains('dark')); - }); - }); - }); - } - +class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MultiProvider( - providers: [ - Provider(create: (context) => SettingsProvider()), - ], - builder: (context, child) { - var isDarkMode = context.watch().settings.isDarkMode; - return isDarkMode == null - ? Center( - child: CircularProgressIndicator(), - ) - : MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: isDarkMode ? Colors.blue : Colors.blue, - brightness: isDarkMode ? Brightness.dark : Brightness.light, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); - }); + providers: [ + ChangeNotifierProvider(create: (context) => SettingsProvider()), + ], + builder: (context, child) { + var isDarkMode = context.watch().isDarkMode; + return AnimatedCrossFade( + crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond, + alignment: Alignment.center, + layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Positioned(key: bottomChildKey, child: bottomChild), + Positioned(key: topChildKey, child: topChild), + ], + ), + firstChild: MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: isDarkMode == true ? Colors.blue : Colors.blue, + brightness: isDarkMode == true ? Brightness.dark : Brightness.light, + ), + home: MyHomePage(title: 'Flutter Demo Home Page'), + ), + secondChild: Builder(builder: (_) { + var xsettings = GSettings('com.deepin.xsettings'); + xsettings.get('theme-name').then((value) { + Future.delayed( + Duration(seconds: 1), + () => context.read().setProps(isDarkMode: value.toString().contains('dark')), + ); + }); + xsettings.keysChanged.listen((event) { + xsettings.get('theme-name').then((value) { + context.read().setProps(isDarkMode: value.toString().contains('dark')); + }); + }); + return CircularProgressIndicator(); + }), + duration: Duration(seconds: 1), + ); + }, + ); } } diff --git a/app/lib/models/settings.dart b/app/lib/models/settings.dart index 60de8f8..12ee534 100644 --- a/app/lib/models/settings.dart +++ b/app/lib/models/settings.dart @@ -1,29 +1,18 @@ import 'package:flutter/foundation.dart'; class Settings { - Settings({ - this.isDarkMode, - }); + bool? _isDarkMode; - bool? isDarkMode; + bool? get isDarkMode => _isDarkMode; } -class SettingsProvider extends ChangeNotifier { - Settings _settings = Settings(); - - Settings get settings => _settings; - - set settings(Settings newSettings) { - _settings = newSettings; - notifyListeners(); - } - +class SettingsProvider extends Settings with ChangeNotifier { void setProps({ bool? isDarkMode, }) { bool changed = false; - if (isDarkMode != _settings.isDarkMode) { - _settings.isDarkMode = isDarkMode; + if (this._isDarkMode != isDarkMode) { + this._isDarkMode = isDarkMode; changed = true; } if (changed) notifyListeners(); -- 2.11.0 From 9fa94e38a7529aa7bfcb84988d896cdd6f3b3532 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Sat, 18 Sep 2021 18:28:35 +0800 Subject: [PATCH 3/7] wip: add provider generator. --- app/README.md | 51 ++++++++++++++++---- app/build.yaml | 11 +++++ app/lib/builder/provider_annotation.dart | 9 ++++ app/lib/builder/provider_builder.dart | 6 +++ app/lib/builder/provider_generator.dart | 48 +++++++++++++++++++ app/lib/extensions/compare_extension.dart | 3 ++ app/lib/extensions/sout_extension.dart | 12 +++++ app/lib/main.dart | 77 +++++++++++-------------------- app/lib/models/settings.dart | 22 +++------ app/lib/utils/helper.dart | 17 ++++++- app/lib/utils/init.dart | 1 + app/lib/utils/init_linux.dart | 34 ++++++++++++++ app/lib/utils/init_web.dart | 13 ++++++ app/pubspec.yaml | 2 + 14 files changed, 228 insertions(+), 78 deletions(-) create mode 100644 app/build.yaml create mode 100644 app/lib/builder/provider_annotation.dart create mode 100644 app/lib/builder/provider_builder.dart create mode 100644 app/lib/builder/provider_generator.dart create mode 100644 app/lib/extensions/compare_extension.dart create mode 100644 app/lib/extensions/sout_extension.dart create mode 100644 app/lib/utils/init.dart create mode 100644 app/lib/utils/init_linux.dart create mode 100644 app/lib/utils/init_web.dart diff --git a/app/README.md b/app/README.md index d446fd0..a6629fe 100644 --- a/app/README.md +++ b/app/README.md @@ -1,16 +1,47 @@ -# dde_gesture_manager +# DDE Gesture Manager +专为 DDE 桌面环境打造的触摸板手势管理工具 -A new Flutter project. +## ProviderGenerator +利用 [source_gen](https://pub.dev/packages/source_gen) 和 [build_runner](https://pub.flutter-io.cn/packages/build_runner) 生成 [provider](https://pub.flutter-io.cn/packages/provider) 的模板代码: +1. 在 `lib/models/` 下编写模型类 +```dart +import 'package:dde_gesture_manager/builder/provider_annotation.dart'; -## Getting Started +@ProviderModel() +class Test { + @ProviderModelProp() + bool? tested; -This project is a starting point for a Flutter application. + @ProviderModelProp() + String? name; +} -A few resources to get you started if this is your first Flutter project: +``` -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) +2. `app` 项目目录下执行 `flutter packages pub run build_runner build` -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +3. 将在 `lib/models/test.provider.dart` 生成如下代码: +```dart +import 'package:flutter/foundation.dart'; +import 'package:dde_gesture_manager/extensions/compare_extension.dart'; +import 'test.dart'; + +class TestProvider extends Test with ChangeNotifier { + void setProps({ + bool? tested, + String? name, + }) { + bool changed = false; + if (tested.diff(this.tested)) { + this.tested = tested; + changed = true; + } + if (name.diff(this.name)) { + this.name = name; + changed = true; + } + if (changed) notifyListeners(); + } +} + +``` diff --git a/app/build.yaml b/app/build.yaml new file mode 100644 index 0000000..710187a --- /dev/null +++ b/app/build.yaml @@ -0,0 +1,11 @@ +builders: + provider_builder: + import: 'lib/builder/provider_builder.dart' + builder_factories: [ 'providerBuilder' ] + build_extensions: { '.dart': [ '.provider.dart' ] } + auto_apply: root_package + build_to: source + defaults: + generate_for: + include: + - lib/models/** diff --git a/app/lib/builder/provider_annotation.dart b/app/lib/builder/provider_annotation.dart new file mode 100644 index 0000000..3f66ed0 --- /dev/null +++ b/app/lib/builder/provider_annotation.dart @@ -0,0 +1,9 @@ +class ProviderModel { + const ProviderModel(); +} + +class ProviderModelProp { + const ProviderModelProp({this.nullable = true}); + + final bool nullable; +} diff --git a/app/lib/builder/provider_builder.dart b/app/lib/builder/provider_builder.dart new file mode 100644 index 0000000..42f92e8 --- /dev/null +++ b/app/lib/builder/provider_builder.dart @@ -0,0 +1,6 @@ +import 'package:dde_gesture_manager/builder/provider_generator.dart'; +import 'package:source_gen/source_gen.dart'; +import 'package:build/build.dart'; + +Builder providerBuilder(BuilderOptions options) => + LibraryBuilder(ProviderGenerator(), generatedExtension: '.provider.dart'); diff --git a/app/lib/builder/provider_generator.dart b/app/lib/builder/provider_generator.dart new file mode 100644 index 0000000..14fc6bc --- /dev/null +++ b/app/lib/builder/provider_generator.dart @@ -0,0 +1,48 @@ +import 'package:analyzer/dart/element/element.dart'; +import 'package:build/src/builder/build_step.dart'; +import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +import 'package:source_gen/source_gen.dart'; +import 'package:collection/collection.dart'; + +class AnnotationField { + String name; + String type; + + AnnotationField(this.name, this.type); +} + +class ProviderGenerator extends GeneratorForAnnotation { + @override + generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) { + var className = (element as ClassElement).source.shortName; + List fields = []; + element.fields.forEach((field) { + var annotation = field.metadata.firstWhereOrNull( + (m) => m.computeConstantValue()?.type?.getDisplayString(withNullability: true) == 'ProviderModelProp'); + if (annotation != null) + fields.add( + AnnotationField( + field.displayName, + field.type.getDisplayString( + withNullability: annotation.computeConstantValue()?.getField('nullable')?.toBoolValue() ?? true, + ), + ), + ); + }); + return ''' +import 'package:flutter/foundation.dart'; +import 'package:dde_gesture_manager/extensions/compare_extension.dart'; +import '$className'; + +class ${element.displayName}Provider extends ${element.displayName} with ChangeNotifier { + void setProps({ + ${fields.map((f) => '${f.type.endsWith('?') ? '' : 'required '}${f.type} ${f.name},').join('\n')} + }) { + bool changed = false; + ${fields.map((f) => 'if (${f.name}.diff(this.${f.name})) {this.${f.name} = ${f.name}; changed = true; }').join('\n')} + if (changed) notifyListeners(); + } +} + '''; + } +} diff --git a/app/lib/extensions/compare_extension.dart b/app/lib/extensions/compare_extension.dart new file mode 100644 index 0000000..7d54d64 --- /dev/null +++ b/app/lib/extensions/compare_extension.dart @@ -0,0 +1,3 @@ +extension CompareExtension on Object? { + bool diff(other) => this != null && this != other; +} diff --git a/app/lib/extensions/sout_extension.dart b/app/lib/extensions/sout_extension.dart new file mode 100644 index 0000000..c1ad104 --- /dev/null +++ b/app/lib/extensions/sout_extension.dart @@ -0,0 +1,12 @@ +extension SoutExtension on Object? { + void sout() { + switch (this.runtimeType) { + case String: + return print(this); + case Null: + return print(null); + default: + return print(this.toString()); + } + } +} diff --git a/app/lib/main.dart b/app/lib/main.dart index 1318877..8382e84 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,29 +1,13 @@ -import 'package:dde_gesture_manager/models/settings.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:dde_gesture_manager/utils/init.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -import 'package:gsettings/gsettings.dart'; import 'package:provider/provider.dart'; -import 'package:window_manager/window_manager.dart'; -import 'package:xdg_directories/xdg_directories.dart' as xdgDir; Future main() async { WidgetsFlutterBinding.ensureInitialized(); - if (!kIsWeb) { - print(await xdgDir.configHome); - print(await xdgDir.cacheHome); - print(await xdgDir.dataHome); - print('------'); - print(await xdgDir.configDirs.join('\n')); - print('------'); - print(await xdgDir.dataDirs.join('\n')); - print('------'); - print(await xdgDir.runtimeDir); - print('------'); - var windowManager = WindowManager.instance; - windowManager.setTitle('Gesture Manager For DDE'); - windowManager.setMinimumSize(const Size(800, 600)); - } + await initConfigs(); runApp(MyApp()); } @@ -36,41 +20,32 @@ class MyApp extends StatelessWidget { ], builder: (context, child) { var isDarkMode = context.watch().isDarkMode; - return AnimatedCrossFade( - crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond, - alignment: Alignment.center, - layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Positioned(key: bottomChildKey, child: bottomChild), - Positioned(key: topChildKey, child: topChild), - ], + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: isDarkMode == true ? Colors.blue : Colors.blue, + brightness: isDarkMode == true ? Brightness.dark : Brightness.light, ), - firstChild: MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: isDarkMode == true ? Colors.blue : Colors.blue, - brightness: isDarkMode == true ? Brightness.dark : Brightness.light, + home: AnimatedCrossFade( + crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond, + alignment: Alignment.center, + layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Positioned(key: bottomChildKey, child: bottomChild), + Positioned(key: topChildKey, child: topChild), + ], ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ), - secondChild: Builder(builder: (_) { - var xsettings = GSettings('com.deepin.xsettings'); - xsettings.get('theme-name').then((value) { - Future.delayed( - Duration(seconds: 1), - () => context.read().setProps(isDarkMode: value.toString().contains('dark')), + firstChild: MyHomePage(title: 'Flutter Demo Home Page'), + secondChild: Builder(builder: (context) { + initEvents(context); + return Center( + child: CircularProgressIndicator(), ); - }); - xsettings.keysChanged.listen((event) { - xsettings.get('theme-name').then((value) { - context.read().setProps(isDarkMode: value.toString().contains('dark')); - }); - }); - return CircularProgressIndicator(); - }), - duration: Duration(seconds: 1), + }), + duration: Duration(seconds: 1), + ), ); }, ); diff --git a/app/lib/models/settings.dart b/app/lib/models/settings.dart index 12ee534..06b4c8f 100644 --- a/app/lib/models/settings.dart +++ b/app/lib/models/settings.dart @@ -1,20 +1,10 @@ -import 'package:flutter/foundation.dart'; +import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +@ProviderModel() class Settings { - bool? _isDarkMode; + @ProviderModelProp() + bool? isDarkMode; - bool? get isDarkMode => _isDarkMode; -} - -class SettingsProvider extends Settings with ChangeNotifier { - void setProps({ - bool? isDarkMode, - }) { - bool changed = false; - if (this._isDarkMode != isDarkMode) { - this._isDarkMode = isDarkMode; - changed = true; - } - if (changed) notifyListeners(); - } + @ProviderModelProp() + String? name; } diff --git a/app/lib/utils/helper.dart b/app/lib/utils/helper.dart index 682c2c1..f306e6a 100644 --- a/app/lib/utils/helper.dart +++ b/app/lib/utils/helper.dart @@ -1,2 +1,17 @@ +import 'package:shared_preferences/shared_preferences.dart'; + class H { -} \ No newline at end of file + H._(); + + static final _h = H._(); + + factory H() => _h; + + late SharedPreferences _sp; + + SharedPreferences get sp => _sp; + + initSharedPreference() async { + _sp = await SharedPreferences.getInstance(); + } +} diff --git a/app/lib/utils/init.dart b/app/lib/utils/init.dart new file mode 100644 index 0000000..edafa2a --- /dev/null +++ b/app/lib/utils/init.dart @@ -0,0 +1 @@ +export 'init_web.dart' if (dart.library.io) 'init_linux.dart'; diff --git a/app/lib/utils/init_linux.dart b/app/lib/utils/init_linux.dart new file mode 100644 index 0000000..4291835 --- /dev/null +++ b/app/lib/utils/init_linux.dart @@ -0,0 +1,34 @@ +import 'package:dde_gesture_manager/utils/helper.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:gsettings/gsettings.dart'; +import 'package:provider/provider.dart'; +import 'package:window_manager/window_manager.dart'; +import 'package:dde_gesture_manager/models/settings.provider.dart'; + +Future initEvents(BuildContext context) async { + var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark; + if (isDark) { + context.read().setProps(isDarkMode: isDark); + } else { + var xsettings = GSettings('com.deepin.xsettings'); + xsettings.get('theme-name').then((value) { + Future.delayed( + Duration(seconds: 1), + () => context.read().setProps(isDarkMode: value.toString().contains('dark')), + ); + }); + xsettings.keysChanged.listen((event) { + xsettings.get('theme-name').then((value) { + context.read().setProps(isDarkMode: value.toString().contains('dark')); + }); + }); + } +} + +Future initConfigs() async { + await H().initSharedPreference(); + var windowManager = WindowManager.instance; + windowManager.setTitle('Gesture Manager For DDE'); + windowManager.setMinimumSize(const Size(800, 600)); +} diff --git a/app/lib/utils/init_web.dart b/app/lib/utils/init_web.dart new file mode 100644 index 0000000..8fe0d79 --- /dev/null +++ b/app/lib/utils/init_web.dart @@ -0,0 +1,13 @@ +import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:dde_gesture_manager/utils/helper.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +Future initEvents(BuildContext context) async { + var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark; + context.read().setProps(isDarkMode: isDark); +} + +Future initConfigs() async { + await H().initSharedPreference(); +} diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 446340f..25d41f5 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -38,6 +38,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + build_runner: 2.1.2 + source_gen: 1.1.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec -- 2.11.0 From aa2454553c233bd0919636b086a212de8f5d4e34 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Thu, 23 Sep 2021 15:43:47 +0800 Subject: [PATCH 4/7] wip: fix issues. --- app/README.md | 2 +- app/lib/constants/sp_keys.dart | 3 ++ app/lib/main.dart | 63 +++++++++++++++++++++++++++++++++++------- app/lib/models/configs.dart | 19 +++++++++++++ app/lib/models/settings.dart | 3 -- app/lib/utils/init_linux.dart | 26 +++++++++-------- 6 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 app/lib/constants/sp_keys.dart create mode 100644 app/lib/models/configs.dart diff --git a/app/README.md b/app/README.md index a6629fe..0649c9c 100644 --- a/app/README.md +++ b/app/README.md @@ -18,7 +18,7 @@ class Test { ``` -2. `app` 项目目录下执行 `flutter packages pub run build_runner build` +2. `app` 项目目录下执行 `flutter packages pub get && flutter packages pub run build_runner build --delete-conflicting-outputs` 3. 将在 `lib/models/test.provider.dart` 生成如下代码: ```dart diff --git a/app/lib/constants/sp_keys.dart b/app/lib/constants/sp_keys.dart new file mode 100644 index 0000000..d3b1d79 --- /dev/null +++ b/app/lib/constants/sp_keys.dart @@ -0,0 +1,3 @@ +class SPKeys { + static final String brightnessMode = 'BRIGHTNESS_MODE'; +} \ No newline at end of file diff --git a/app/lib/main.dart b/app/lib/main.dart index 8382e84..6dc37f6 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,3 +1,5 @@ +import 'package:dde_gesture_manager/models/configs.dart'; +import 'package:dde_gesture_manager/models/configs.provider.dart'; import 'package:dde_gesture_manager/models/settings.provider.dart'; import 'package:dde_gesture_manager/utils/init.dart'; import 'package:flutter/foundation.dart'; @@ -17,17 +19,25 @@ class MyApp extends StatelessWidget { return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => SettingsProvider()), + ChangeNotifierProvider(create: (context) => ConfigsProvider()), ], builder: (context, child) { var isDarkMode = context.watch().isDarkMode; + var brightnessMode = context.watch().brightnessMode; + late bool showDarkMode; + if (brightnessMode == BrightnessMode.system) { + showDarkMode = isDarkMode ?? false; + } else { + showDarkMode = brightnessMode == BrightnessMode.dark; + } return MaterialApp( title: 'Flutter Demo', theme: ThemeData( - primarySwatch: isDarkMode == true ? Colors.blue : Colors.blue, - brightness: isDarkMode == true ? Brightness.dark : Brightness.light, + primarySwatch: showDarkMode ? Colors.blue : Colors.blue, + brightness: showDarkMode ? Brightness.dark : Brightness.light, ), home: AnimatedCrossFade( - crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond, + crossFadeState: isDarkMode != null ? CrossFadeState.showSecond : CrossFadeState.showFirst, alignment: Alignment.center, layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack( clipBehavior: Clip.none, @@ -37,14 +47,12 @@ class MyApp extends StatelessWidget { Positioned(key: topChildKey, child: topChild), ], ), - firstChild: MyHomePage(title: 'Flutter Demo Home Page'), - secondChild: Builder(builder: (context) { - initEvents(context); - return Center( - child: CircularProgressIndicator(), - ); + firstChild: Builder(builder: (context) { + Future.microtask(() => initEvents(context)); + return Container(); }), - duration: Duration(seconds: 1), + secondChild: MyHomePage(title: 'Flutter Demo Home Page'), + duration: Duration(milliseconds: 500), ), ); }, @@ -72,6 +80,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { + var brightnessMode = context.watch().brightnessMode; return Scaffold( appBar: AppBar( title: Text(widget.title), @@ -87,6 +96,40 @@ class _MyHomePageState extends State { '$_counter', style: Theme.of(context).textTheme.headline4, ), + ListTile( + title: const Text('System'), + leading: Radio( + value: BrightnessMode.system, + groupValue: brightnessMode, + onChanged: (BrightnessMode? value) { + context.read().setProps(brightnessMode: value); + }, + ), + ), + ListTile( + title: const Text('Light'), + leading: Radio( + value: BrightnessMode.light, + groupValue: brightnessMode, + onChanged: (BrightnessMode? value) { + setState(() { + context.read().setProps(brightnessMode: value); + }); + }, + ), + ), + ListTile( + title: const Text('Dark'), + leading: Radio( + value: BrightnessMode.dark, + groupValue: brightnessMode, + onChanged: (BrightnessMode? value) { + setState(() { + context.read().setProps(brightnessMode: value); + }); + }, + ), + ), ], ), ), diff --git a/app/lib/models/configs.dart b/app/lib/models/configs.dart new file mode 100644 index 0000000..f8822b1 --- /dev/null +++ b/app/lib/models/configs.dart @@ -0,0 +1,19 @@ +import 'package:dde_gesture_manager/builder/provider_annotation.dart'; +import 'package:dde_gesture_manager/constants/sp_keys.dart'; +import 'package:dde_gesture_manager/utils/helper.dart'; + +enum BrightnessMode { + system, + light, + dark, +} + +@ProviderModel() +class Configs { + @ProviderModelProp() + BrightnessMode? brightnessMode; + + Configs() { + this.brightnessMode = BrightnessMode.values[H().sp.getInt(SPKeys.brightnessMode)?.clamp(0, 2) ?? 0]; + } +} diff --git a/app/lib/models/settings.dart b/app/lib/models/settings.dart index 06b4c8f..27a264d 100644 --- a/app/lib/models/settings.dart +++ b/app/lib/models/settings.dart @@ -4,7 +4,4 @@ import 'package:dde_gesture_manager/builder/provider_annotation.dart'; class Settings { @ProviderModelProp() bool? isDarkMode; - - @ProviderModelProp() - String? name; } diff --git a/app/lib/utils/init_linux.dart b/app/lib/utils/init_linux.dart index 4291835..02e7fed 100644 --- a/app/lib/utils/init_linux.dart +++ b/app/lib/utils/init_linux.dart @@ -1,5 +1,4 @@ import 'package:dde_gesture_manager/utils/helper.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gsettings/gsettings.dart'; import 'package:provider/provider.dart'; @@ -12,17 +11,22 @@ Future initEvents(BuildContext context) async { context.read().setProps(isDarkMode: isDark); } else { var xsettings = GSettings('com.deepin.xsettings'); - xsettings.get('theme-name').then((value) { - Future.delayed( - Duration(seconds: 1), - () => context.read().setProps(isDarkMode: value.toString().contains('dark')), - ); - }); - xsettings.keysChanged.listen((event) { - xsettings.get('theme-name').then((value) { - context.read().setProps(isDarkMode: value.toString().contains('dark')); + String? themeName; + try { + themeName = (await xsettings.get('theme-name')).toString(); + } catch (e) { + print(e); + context.read().setProps(isDarkMode: false); + } + + if (themeName != null) { + context.read().setProps(isDarkMode: themeName.contains('dark')); + xsettings.keysChanged.listen((event) { + xsettings.get('theme-name').then((value) { + context.read().setProps(isDarkMode: value.toString().contains('dark')); + }); }); - }); + } } } -- 2.11.0 From aa2f50233f620fb3686fc0a88c90db114cf57fab Mon Sep 17 00:00:00 2001 From: debuggerx Date: Thu, 23 Sep 2021 18:40:12 +0800 Subject: [PATCH 5/7] wip: add easy_localization. --- api/lib/channel.dart | 2 +- api/test/harness/app.dart | 6 +- app/README.md | 8 +++ app/lib/extensions.dart | 9 +++ app/lib/extensions/context_extension.dart | 8 +++ app/lib/extensions/string_extension.dart | 3 + app/lib/main.dart | 107 +++++------------------------- app/lib/pages/home.dart | 33 +++++++++ app/lib/themes/dark.dart | 5 ++ app/lib/themes/light.dart | 5 ++ app/lib/widgets/footer.dart | 47 +++++++++++++ app/pubspec.yaml | 4 +- app/resources/langs/en.json | 8 +++ app/resources/langs/zh-CN.json | 8 +++ 14 files changed, 159 insertions(+), 94 deletions(-) create mode 100644 app/lib/extensions.dart create mode 100644 app/lib/extensions/context_extension.dart create mode 100644 app/lib/extensions/string_extension.dart create mode 100644 app/lib/pages/home.dart create mode 100644 app/lib/themes/dark.dart create mode 100644 app/lib/themes/light.dart create mode 100644 app/lib/widgets/footer.dart create mode 100644 app/resources/langs/en.json create mode 100644 app/resources/langs/zh-CN.json diff --git a/api/lib/channel.dart b/api/lib/channel.dart index 8a95282..2eeca45 100644 --- a/api/lib/channel.dart +++ b/api/lib/channel.dart @@ -1,5 +1,5 @@ -import 'package:dde_gesture_manager/model/model.dart'; import 'package:dde_gesture_manager/dde_gesture_manager.dart'; +import 'package:dde_gesture_manager/model/model.dart'; /// This type initializes an application. /// diff --git a/api/test/harness/app.dart b/api/test/harness/app.dart index 029207a..a78b76f 100644 --- a/api/test/harness/app.dart +++ b/api/test/harness/app.dart @@ -1,10 +1,10 @@ -import 'package:dde_gesture_manager/dde_gesture_manager.dart'; import 'package:conduit_test/conduit_test.dart'; +import 'package:dde_gesture_manager/dde_gesture_manager.dart'; -export 'package:dde_gesture_manager/dde_gesture_manager.dart'; +export 'package:conduit/conduit.dart'; export 'package:conduit_test/conduit_test.dart'; +export 'package:dde_gesture_manager/dde_gesture_manager.dart'; export 'package:test/test.dart'; -export 'package:conduit/conduit.dart'; /// A testing harness for dde_gesture_manager. /// diff --git a/app/README.md b/app/README.md index 0649c9c..a7411e9 100644 --- a/app/README.md +++ b/app/README.md @@ -45,3 +45,11 @@ class TestProvider extends Test with ChangeNotifier { } ``` + +## easy_localization +### 生成资源代码 +`flutter pub run easy_localization:generate && flutter pub run easy_localization:generate -f keys -o locale_keys.g.dart` + +### 已经支持语言 +- 简体中文(zh-CN) +- English(en) diff --git a/app/lib/extensions.dart b/app/lib/extensions.dart new file mode 100644 index 0000000..6bb96f2 --- /dev/null +++ b/app/lib/extensions.dart @@ -0,0 +1,9 @@ +library extensions; + +export 'package:dde_gesture_manager/extensions/sout_extension.dart'; +export 'package:dde_gesture_manager/extensions/string_extension.dart'; +export 'package:dde_gesture_manager/extensions/context_extension.dart'; +export 'package:dde_gesture_manager/generated/locale_keys.g.dart'; +export 'package:easy_localization/easy_localization.dart'; + +export 'package:provider/provider.dart'; \ No newline at end of file diff --git a/app/lib/extensions/context_extension.dart b/app/lib/extensions/context_extension.dart new file mode 100644 index 0000000..5607fb6 --- /dev/null +++ b/app/lib/extensions/context_extension.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +extension ContextExtension on BuildContext { + ThemeData get t => Theme.of(this); + + NavigatorState get n => Navigator.of(this); +} diff --git a/app/lib/extensions/string_extension.dart b/app/lib/extensions/string_extension.dart new file mode 100644 index 0000000..6432f1b --- /dev/null +++ b/app/lib/extensions/string_extension.dart @@ -0,0 +1,3 @@ +extension StringNotNull on String? { + bool get notNull => this != null && this != ''; +} \ No newline at end of file diff --git a/app/lib/main.dart b/app/lib/main.dart index 6dc37f6..20f5b51 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,16 +1,30 @@ +import 'package:dde_gesture_manager/generated/codegen_loader.g.dart'; import 'package:dde_gesture_manager/models/configs.dart'; import 'package:dde_gesture_manager/models/configs.provider.dart'; import 'package:dde_gesture_manager/models/settings.provider.dart'; +import 'package:dde_gesture_manager/themes/dark.dart'; +import 'package:dde_gesture_manager/themes/light.dart'; import 'package:dde_gesture_manager/utils/init.dart'; -import 'package:flutter/foundation.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; +import 'pages/home.dart'; + Future main() async { WidgetsFlutterBinding.ensureInitialized(); await initConfigs(); - runApp(MyApp()); + runApp(EasyLocalization( + supportedLocales: [ + Locale('zh', 'CN'), + Locale('en'), + ], + fallbackLocale: Locale('zh', 'CN'), + path: 'resources/langs', + assetLoader: CodegenLoader(), + child: MyApp(), + )); } class MyApp extends StatelessWidget { @@ -32,10 +46,7 @@ class MyApp extends StatelessWidget { } return MaterialApp( title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: showDarkMode ? Colors.blue : Colors.blue, - brightness: showDarkMode ? Brightness.dark : Brightness.light, - ), + theme: showDarkMode ? darkTheme : lightTheme, home: AnimatedCrossFade( crossFadeState: isDarkMode != null ? CrossFadeState.showSecond : CrossFadeState.showFirst, alignment: Alignment.center, @@ -51,7 +62,7 @@ class MyApp extends StatelessWidget { Future.microtask(() => initEvents(context)); return Container(); }), - secondChild: MyHomePage(title: 'Flutter Demo Home Page'), + secondChild: HomePage(), duration: Duration(milliseconds: 500), ), ); @@ -59,85 +70,3 @@ class MyApp extends StatelessWidget { ); } } - -class MyHomePage extends StatefulWidget { - MyHomePage({Key? key, required this.title}) : super(key: key); - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - var brightnessMode = context.watch().brightnessMode; - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - ListTile( - title: const Text('System'), - leading: Radio( - value: BrightnessMode.system, - groupValue: brightnessMode, - onChanged: (BrightnessMode? value) { - context.read().setProps(brightnessMode: value); - }, - ), - ), - ListTile( - title: const Text('Light'), - leading: Radio( - value: BrightnessMode.light, - groupValue: brightnessMode, - onChanged: (BrightnessMode? value) { - setState(() { - context.read().setProps(brightnessMode: value); - }); - }, - ), - ), - ListTile( - title: const Text('Dark'), - leading: Radio( - value: BrightnessMode.dark, - groupValue: brightnessMode, - onChanged: (BrightnessMode? value) { - setState(() { - context.read().setProps(brightnessMode: value); - }); - }, - ), - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), - ); - } -} diff --git a/app/lib/pages/home.dart b/app/lib/pages/home.dart new file mode 100644 index 0000000..53368dc --- /dev/null +++ b/app/lib/pages/home.dart @@ -0,0 +1,33 @@ +import 'package:dde_gesture_manager/widgets/footer.dart'; +import 'package:flutter/material.dart'; + +class HomePage extends StatefulWidget { + const HomePage({Key? key}) : super(key: key); + + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text('asd'), + ], + ), + SizedBox( + height: 32, + child: Footer(), + ), + ], + ), + ); + } +} diff --git a/app/lib/themes/dark.dart b/app/lib/themes/dark.dart new file mode 100644 index 0000000..c7d3266 --- /dev/null +++ b/app/lib/themes/dark.dart @@ -0,0 +1,5 @@ +import 'package:flutter/material.dart'; + +var darkTheme = ThemeData.dark().copyWith( + primaryColor: Colors.grey, +); diff --git a/app/lib/themes/light.dart b/app/lib/themes/light.dart new file mode 100644 index 0000000..4939083 --- /dev/null +++ b/app/lib/themes/light.dart @@ -0,0 +1,5 @@ +import 'package:flutter/material.dart'; + +var lightTheme = ThemeData.light().copyWith( + primaryColor: Colors.blue, +); \ No newline at end of file diff --git a/app/lib/widgets/footer.dart b/app/lib/widgets/footer.dart new file mode 100644 index 0000000..2b0f641 --- /dev/null +++ b/app/lib/widgets/footer.dart @@ -0,0 +1,47 @@ +import 'package:dde_gesture_manager/models/configs.dart'; +import 'package:dde_gesture_manager/models/configs.provider.dart'; +import 'package:flutter/material.dart'; +import 'package:dde_gesture_manager/extensions.dart'; + +class Footer extends StatefulWidget { + const Footer({Key? key}) : super(key: key); + + @override + _FooterState createState() => _FooterState(); +} + +class _FooterState extends State