wip: add provider generator.
This commit is contained in:
+41
-10
@@ -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)
|
2. `app` 项目目录下执行 `flutter packages pub run build_runner build`
|
||||||
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
|
||||||
|
|
||||||
For help getting started with Flutter, view our
|
3. 将在 `lib/models/test.provider.dart` 生成如下代码:
|
||||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
```dart
|
||||||
samples, guidance on mobile development, and a full API reference.
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
@@ -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/**
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class ProviderModel {
|
||||||
|
const ProviderModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProviderModelProp {
|
||||||
|
const ProviderModelProp({this.nullable = true});
|
||||||
|
|
||||||
|
final bool nullable;
|
||||||
|
}
|
||||||
@@ -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');
|
||||||
@@ -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<ProviderModel> {
|
||||||
|
@override
|
||||||
|
generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) {
|
||||||
|
var className = (element as ClassElement).source.shortName;
|
||||||
|
List<AnnotationField> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
''';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
extension CompareExtension on Object? {
|
||||||
|
bool diff(other) => this != null && this != other;
|
||||||
|
}
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-51
@@ -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/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:gsettings/gsettings.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
|
||||||
import 'package:xdg_directories/xdg_directories.dart' as xdgDir;
|
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
if (!kIsWeb) {
|
await initConfigs();
|
||||||
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));
|
|
||||||
}
|
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,41 +20,32 @@ class MyApp extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
var isDarkMode = context.watch<SettingsProvider>().isDarkMode;
|
var isDarkMode = context.watch<SettingsProvider>().isDarkMode;
|
||||||
return AnimatedCrossFade(
|
return MaterialApp(
|
||||||
crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond,
|
title: 'Flutter Demo',
|
||||||
alignment: Alignment.center,
|
theme: ThemeData(
|
||||||
layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack(
|
primarySwatch: isDarkMode == true ? Colors.blue : Colors.blue,
|
||||||
clipBehavior: Clip.none,
|
brightness: isDarkMode == true ? Brightness.dark : Brightness.light,
|
||||||
|
),
|
||||||
|
home: AnimatedCrossFade(
|
||||||
|
crossFadeState: isDarkMode != null ? CrossFadeState.showFirst : CrossFadeState.showSecond,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: <Widget>[
|
layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) => Stack(
|
||||||
Positioned(key: bottomChildKey, child: bottomChild),
|
clipBehavior: Clip.none,
|
||||||
Positioned(key: topChildKey, child: topChild),
|
alignment: Alignment.center,
|
||||||
],
|
children: <Widget>[
|
||||||
),
|
Positioned(key: bottomChildKey, child: bottomChild),
|
||||||
firstChild: MaterialApp(
|
Positioned(key: topChildKey, child: topChild),
|
||||||
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'),
|
firstChild: MyHomePage(title: 'Flutter Demo Home Page'),
|
||||||
),
|
secondChild: Builder(builder: (context) {
|
||||||
secondChild: Builder(builder: (_) {
|
initEvents(context);
|
||||||
var xsettings = GSettings('com.deepin.xsettings');
|
return Center(
|
||||||
xsettings.get('theme-name').then((value) {
|
child: CircularProgressIndicator(),
|
||||||
Future.delayed(
|
|
||||||
Duration(seconds: 1),
|
|
||||||
() => context.read<SettingsProvider>().setProps(isDarkMode: value.toString().contains('dark')),
|
|
||||||
);
|
);
|
||||||
});
|
}),
|
||||||
xsettings.keysChanged.listen((event) {
|
duration: Duration(seconds: 1),
|
||||||
xsettings.get('theme-name').then((value) {
|
),
|
||||||
context.read<SettingsProvider>().setProps(isDarkMode: value.toString().contains('dark'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return CircularProgressIndicator();
|
|
||||||
}),
|
|
||||||
duration: Duration(seconds: 1),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||||
|
|
||||||
|
@ProviderModel()
|
||||||
class Settings {
|
class Settings {
|
||||||
bool? _isDarkMode;
|
@ProviderModelProp()
|
||||||
|
bool? isDarkMode;
|
||||||
|
|
||||||
bool? get isDarkMode => _isDarkMode;
|
@ProviderModelProp()
|
||||||
}
|
String? name;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,17 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class H {
|
class H {
|
||||||
}
|
H._();
|
||||||
|
|
||||||
|
static final _h = H._();
|
||||||
|
|
||||||
|
factory H() => _h;
|
||||||
|
|
||||||
|
late SharedPreferences _sp;
|
||||||
|
|
||||||
|
SharedPreferences get sp => _sp;
|
||||||
|
|
||||||
|
initSharedPreference() async {
|
||||||
|
_sp = await SharedPreferences.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export 'init_web.dart' if (dart.library.io) '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<void> initEvents(BuildContext context) async {
|
||||||
|
var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark;
|
||||||
|
if (isDark) {
|
||||||
|
context.read<SettingsProvider>().setProps(isDarkMode: isDark);
|
||||||
|
} else {
|
||||||
|
var xsettings = GSettings('com.deepin.xsettings');
|
||||||
|
xsettings.get('theme-name').then((value) {
|
||||||
|
Future.delayed(
|
||||||
|
Duration(seconds: 1),
|
||||||
|
() => context.read<SettingsProvider>().setProps(isDarkMode: value.toString().contains('dark')),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
xsettings.keysChanged.listen((event) {
|
||||||
|
xsettings.get('theme-name').then((value) {
|
||||||
|
context.read<SettingsProvider>().setProps(isDarkMode: value.toString().contains('dark'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initConfigs() async {
|
||||||
|
await H().initSharedPreference();
|
||||||
|
var windowManager = WindowManager.instance;
|
||||||
|
windowManager.setTitle('Gesture Manager For DDE');
|
||||||
|
windowManager.setMinimumSize(const Size(800, 600));
|
||||||
|
}
|
||||||
@@ -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<void> initEvents(BuildContext context) async {
|
||||||
|
var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark;
|
||||||
|
context.read<SettingsProvider>().setProps(isDarkMode: isDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initConfigs() async {
|
||||||
|
await H().initSharedPreference();
|
||||||
|
}
|
||||||
@@ -38,6 +38,8 @@ dependencies:
|
|||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
build_runner: 2.1.2
|
||||||
|
source_gen: 1.1.0
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|||||||
Reference in New Issue
Block a user