diff --git a/apps/flutter/.gitignore b/apps/flutter/.gitignore new file mode 100644 index 000000000..456150bbf --- /dev/null +++ b/apps/flutter/.gitignore @@ -0,0 +1,52 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +.vscode/ + + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +# Environment config +/res/config/development.json + +# Business + +business/ \ No newline at end of file diff --git a/apps/flutter/account/.flutter-plugins b/apps/flutter/account/.flutter-plugins index 48fac27e8..59e378d87 100644 --- a/apps/flutter/account/.flutter-plugins +++ b/apps/flutter/account/.flutter-plugins @@ -1,6 +1,6 @@ # This is a generated file; do not edit or check into version control. -path_provider=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ -path_provider_android=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ -path_provider_foundation=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ -path_provider_linux=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ -path_provider_windows=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ diff --git a/apps/flutter/account/.flutter-plugins-dependencies b/apps/flutter/account/.flutter-plugins-dependencies index 25b653eb3..2be1851c0 100644 --- a/apps/flutter/account/.flutter-plugins-dependencies +++ b/apps/flutter/account/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-14 11:41:46.248683","version":"3.10.5"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-17 09:32:14.474983","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/account/android/local.properties b/apps/flutter/account/android/local.properties index 60b1ce328..1a3be4ff1 100644 --- a/apps/flutter/account/android/local.properties +++ b/apps/flutter/account/android/local.properties @@ -1,2 +1,2 @@ -sdk.dir=%UserProfile%\\AppData\\Local\\Android\\sdk +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/account/lib/index.dart b/apps/flutter/account/lib/index.dart index 999852c0c..1ef41aa75 100644 --- a/apps/flutter/account/lib/index.dart +++ b/apps/flutter/account/lib/index.dart @@ -1,3 +1,2 @@ -export './interceptors/index.dart'; export './services/index.dart'; export 'account.module.dart'; \ No newline at end of file diff --git a/apps/flutter/account/lib/interceptors/index.dart b/apps/flutter/account/lib/interceptors/index.dart deleted file mode 100644 index 4e4f85873..000000000 --- a/apps/flutter/account/lib/interceptors/index.dart +++ /dev/null @@ -1 +0,0 @@ -export 'oauth.api.interceptor.dart'; \ No newline at end of file diff --git a/apps/flutter/account/lib/models/auth.dart b/apps/flutter/account/lib/models/auth.dart deleted file mode 100644 index 6ee9126f9..000000000 --- a/apps/flutter/account/lib/models/auth.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'auth.g.dart'; - -@JsonSerializable() -class PortalLoginProvider { - PortalLoginProvider({ - required this.id, - required this.name, - this.logo, - }); - @JsonKey(name: 'Id') - String id; - @JsonKey(name: 'Name') - String name; - @JsonKey(name: 'Logo') - String? logo; - - factory PortalLoginProvider.fromJson(Map json) => _$PortalLoginProviderFromJson(json); - Map toJson() => _$PortalLoginProviderToJson(this); -} diff --git a/apps/flutter/account/lib/models/auth.g.dart b/apps/flutter/account/lib/models/auth.g.dart deleted file mode 100644 index 1e7e256f2..000000000 --- a/apps/flutter/account/lib/models/auth.g.dart +++ /dev/null @@ -1,22 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'auth.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -PortalLoginProvider _$PortalLoginProviderFromJson(Map json) => - PortalLoginProvider( - id: json['Id'] as String, - name: json['Name'] as String, - logo: json['Logo'] as String?, - ); - -Map _$PortalLoginProviderToJson( - PortalLoginProvider instance) => - { - 'Id': instance.id, - 'Name': instance.name, - 'Logo': instance.logo, - }; diff --git a/apps/flutter/account/lib/models/common.dart b/apps/flutter/account/lib/models/common.dart deleted file mode 100644 index ff3196de8..000000000 --- a/apps/flutter/account/lib/models/common.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'auth.dart'; - -class PortalLoginException implements Exception { - PortalLoginException(this.providers); - List providers; -} \ No newline at end of file diff --git a/apps/flutter/account/lib/pages/login/controller.dart b/apps/flutter/account/lib/pages/login/controller.dart index 9f7f7d638..1c3c6ff94 100644 --- a/apps/flutter/account/lib/pages/login/controller.dart +++ b/apps/flutter/account/lib/pages/login/controller.dart @@ -1,13 +1,11 @@ -import 'package:account/models/auth.dart'; -import 'package:account/models/common.dart'; import 'package:account/pages/login/widget/portal_form.dart'; import 'package:core/index.dart'; import 'package:get/get.dart'; import 'state.dart'; class LoginController extends GetxController { - AuthService get authService => Get.find(); - SessionService get sessionService => Get.find(); + AuthService get authService => injector.get(); + SessionService get sessionService => injector.get(); final Rx _state = Rx(LoginState( loading: false, @@ -28,7 +26,7 @@ class LoginController extends GetxController { void showPortalLoginDialog() { Get.defaultDialog( - title: 'Lable:LoginToPortal'.tr, + title: 'Label:LoginToPortal'.tr, content: Obx(() => PortalForm( portalProviders: state.portalProviders, onSelected: portalLogin, @@ -43,11 +41,11 @@ class LoginController extends GetxController { val?.loading = true; }); try { - var token = await authService.portal(PortalLoginParams( + await authService.portal(PortalLoginParams( enterpriseId: provider?.id, username: state.username.text, password: state.password.text)); - sessionService.refreshToken(token); + //sessionService.refreshToken(token); state.username.clear(); state.password.clear(); Get.back(closeOverlays: true); diff --git a/apps/flutter/account/lib/pages/login/state.dart b/apps/flutter/account/lib/pages/login/state.dart index a5c2eca07..36c99170e 100644 --- a/apps/flutter/account/lib/pages/login/state.dart +++ b/apps/flutter/account/lib/pages/login/state.dart @@ -1,4 +1,4 @@ -import 'package:account/models/auth.dart'; +import 'package:core/models/auth.dart'; import 'package:flutter/material.dart'; class LoginState { diff --git a/apps/flutter/account/lib/pages/login/widget/portal_form.dart b/apps/flutter/account/lib/pages/login/widget/portal_form.dart index c2de0bfe9..7df058c55 100644 --- a/apps/flutter/account/lib/pages/login/widget/portal_form.dart +++ b/apps/flutter/account/lib/pages/login/widget/portal_form.dart @@ -1,4 +1,4 @@ -import 'package:account/models/auth.dart'; +import 'package:core/models/auth.dart'; import 'package:flutter/material.dart'; class PortalForm extends StatelessWidget { diff --git a/apps/flutter/account/lib/pages/user-info/controller.dart b/apps/flutter/account/lib/pages/user-info/controller.dart index b0459ffc7..bb15fae3b 100644 --- a/apps/flutter/account/lib/pages/user-info/controller.dart +++ b/apps/flutter/account/lib/pages/user-info/controller.dart @@ -1,10 +1,11 @@ +import 'package:core/dependency/index.dart'; import 'package:core/models/auth.dart'; import 'package:core/services/index.dart'; import 'package:get/get.dart'; import 'state.dart'; class UserInfoController extends GetxController { - SessionService get sessionService => Get.find(); + SessionService get sessionService => injector.get(); final Rx _state = Rx(UserInfoState()); UserInfoState get state => _state.value; diff --git a/apps/flutter/account/lib/services/auth.service.oauth.dart b/apps/flutter/account/lib/services/auth.service.oauth.dart deleted file mode 100644 index 2f59ef4dd..000000000 --- a/apps/flutter/account/lib/services/auth.service.oauth.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:convert'; - -import 'package:account/models/auth.dart'; -import 'package:account/models/common.dart'; -import 'package:core/models/auth.dart'; -import 'package:core/models/oauth.dart'; -import 'package:core/services/index.dart'; -import 'package:core/tokens/http.token.dart'; -import 'package:dio/dio.dart'; - -class OAuthService extends AuthService { - OAuthService({ - required this.clientId, - this.clientSecret, - }); - RestService get _restService => find(); - - final String clientId; - final String? clientSecret; - - @override - Future password(LoginParams params) { - var request = PasswordTokenRequest( - clientId: clientId, - clientSecret: clientSecret, - userName: params.username, - password: params.password); - return _restService.post('/connect/token', - data: request.toFormUrlencodedData(), - options: Options( - extra: { - HttpTokens.ignoreToken: true, - }, - contentType: 'application/x-www-form-urlencoded', - )).then((res) => Token.fromJson(res.data)); - } - - @override - Future portal(PortalLoginParams params) { - var request = PortalTokenRequest( - clientId: clientId, - clientSecret: clientSecret, - userName: params.username, - password: params.password, - enterpriseId: params.enterpriseId); - return _restService.post('/connect/token', - data: request.toFormUrlencodedData(), - options: Options( - extra: { - HttpTokens.ignoreToken: true, - HttpTokens.ignoreError: true, - }, - contentType: 'application/x-www-form-urlencoded', - )).then((res) => Token.fromJson(res.data)) - .catchError((error) { - var portalProviders = (jsonDecode(error.response.data["Enterprises"]) as List) - .map((e) => PortalLoginProvider.fromJson(e)).toList(); - throw PortalLoginException(portalProviders); - }, test:(error) { - var err = error as dynamic; - if (err?.response?.statusCode == 400 && err?.response?.data != null && - err?.response?.data["Enterprises"] != null) { - return true; - } - return false; - }); - } - - @override - Future phoneNumber(SmsLoginParams params) { - var request = PhoneNumberTokenRequest( - clientId: clientId, - clientSecret: clientSecret, - phoneNumber: params.phonenumber, - code: params.code); - return _restService.post('/connect/token', - data: request.toFormUrlencodedData(), - options: Options( - extra: { - HttpTokens.ignoreToken: true, - }, - contentType: 'application/x-www-form-urlencoded', - )).then((res) => Token.fromJson(res.data)); - } - - @override - Future refreshToken(RefreshTokenParams params) { - var request = RefreshTokenRequest( - clientId: clientId, - clientSecret: clientSecret, - refreshToken: params.refreshToken, - ); - return _restService.post('/connect/token', - data: request.toFormUrlencodedData(), - options: Options( - contentType: 'application/x-www-form-urlencoded', - )).then((res) => Token.fromJson(res.data)); - } - - @override - Future getProfile() { - return _restService.get('/connect/userinfo') - .then((res) => UserProfile.fromJson(res.data)); - } -} \ No newline at end of file diff --git a/apps/flutter/account/lib/services/index.dart b/apps/flutter/account/lib/services/index.dart index 5459885df..e69de29bb 100644 --- a/apps/flutter/account/lib/services/index.dart +++ b/apps/flutter/account/lib/services/index.dart @@ -1 +0,0 @@ -export 'auth.service.oauth.dart'; \ No newline at end of file diff --git a/apps/flutter/account/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/account/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/account/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/account/pubspec.yaml b/apps/flutter/account/pubspec.yaml index 41cefda11..6bd4acea8 100644 --- a/apps/flutter/account/pubspec.yaml +++ b/apps/flutter/account/pubspec.yaml @@ -15,8 +15,8 @@ dependencies: path: '../core' components: path: '../components' - dio: - get: + dio: ^5.2.0+1 + get: ^4.6.5 json_annotation: ^4.8.1 dev_dependencies: diff --git a/apps/flutter/account_core/.flutter-plugins b/apps/flutter/account_core/.flutter-plugins new file mode 100644 index 000000000..22453877b --- /dev/null +++ b/apps/flutter/account_core/.flutter-plugins @@ -0,0 +1,6 @@ +# This is a generated file; do not edit or check into version control. +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.4\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ diff --git a/apps/flutter/account_core/.flutter-plugins-dependencies b/apps/flutter/account_core/.flutter-plugins-dependencies new file mode 100644 index 000000000..fb694d548 --- /dev/null +++ b/apps/flutter/account_core/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-18 08:33:58.742879","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/account_core/.gitignore b/apps/flutter/account_core/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/apps/flutter/account_core/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/apps/flutter/account_core/.metadata b/apps/flutter/account_core/.metadata new file mode 100644 index 000000000..9596faeed --- /dev/null +++ b/apps/flutter/account_core/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: package diff --git a/apps/flutter/account_core/CHANGELOG.md b/apps/flutter/account_core/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/apps/flutter/account_core/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/apps/flutter/account_core/LICENSE b/apps/flutter/account_core/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/apps/flutter/account_core/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/apps/flutter/account_core/README.md b/apps/flutter/account_core/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/apps/flutter/account_core/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/apps/flutter/account_core/analysis_options.yaml b/apps/flutter/account_core/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/apps/flutter/account_core/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/apps/flutter/account_core/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/flutter/account_core/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java new file mode 100644 index 000000000..7eb0d9f93 --- /dev/null +++ b/apps/flutter/account_core/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -0,0 +1,25 @@ +package io.flutter.plugins; + +import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugins.pathprovider.PathProviderPlugin; + +/** + * Generated file. Do not edit. + */ +public final class GeneratedPluginRegistrant { + public static void registerWith(PluginRegistry registry) { + if (alreadyRegisteredWith(registry)) { + return; + } + PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin")); + } + + private static boolean alreadyRegisteredWith(PluginRegistry registry) { + final String key = GeneratedPluginRegistrant.class.getCanonicalName(); + if (registry.hasPlugin(key)) { + return true; + } + registry.registrarFor(key); + return false; + } +} diff --git a/apps/flutter/account_core/android/local.properties b/apps/flutter/account_core/android/local.properties new file mode 100644 index 000000000..1a3be4ff1 --- /dev/null +++ b/apps/flutter/account_core/android/local.properties @@ -0,0 +1,2 @@ +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk +flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/account_core/ios/Flutter/Generated.xcconfig b/apps/flutter/account_core/ios/Flutter/Generated.xcconfig new file mode 100644 index 000000000..bb331ff52 --- /dev/null +++ b/apps/flutter/account_core/ios/Flutter/Generated.xcconfig @@ -0,0 +1,14 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\account_core +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib\main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 +EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/account_core/ios/Flutter/flutter_export_environment.sh b/apps/flutter/account_core/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 000000000..82aa4d88e --- /dev/null +++ b/apps/flutter/account_core/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\account_core" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.h b/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.h new file mode 100644 index 000000000..7a8909271 --- /dev/null +++ b/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.h @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GeneratedPluginRegistrant_h +#define GeneratedPluginRegistrant_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GeneratedPluginRegistrant : NSObject ++ (void)registerWithRegistry:(NSObject*)registry; +@end + +NS_ASSUME_NONNULL_END +#endif /* GeneratedPluginRegistrant_h */ diff --git a/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.m b/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.m new file mode 100644 index 000000000..c0d0cbad8 --- /dev/null +++ b/apps/flutter/account_core/ios/Runner/GeneratedPluginRegistrant.m @@ -0,0 +1,21 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#import "GeneratedPluginRegistrant.h" + +#if __has_include() +#import +#else +@import path_provider_foundation; +#endif + +@implementation GeneratedPluginRegistrant + ++ (void)registerWithRegistry:(NSObject*)registry { + [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]]; +} + +@end diff --git a/apps/flutter/account_core/lib/account.core.module.dart b/apps/flutter/account_core/lib/account.core.module.dart new file mode 100644 index 000000000..7799b17b2 --- /dev/null +++ b/apps/flutter/account_core/lib/account.core.module.dart @@ -0,0 +1,5 @@ +import 'package:core/modularity/index.dart'; + +class AccountCoreModule extends Module { + +} \ No newline at end of file diff --git a/apps/flutter/account_core/lib/index.dart b/apps/flutter/account_core/lib/index.dart new file mode 100644 index 000000000..943aecc33 --- /dev/null +++ b/apps/flutter/account_core/lib/index.dart @@ -0,0 +1 @@ +export 'account.core.module.dart'; \ No newline at end of file diff --git a/apps/flutter/account_core/lib/models/common.dart b/apps/flutter/account_core/lib/models/common.dart new file mode 100644 index 000000000..e69de29bb diff --git a/apps/flutter/account_core/lib/models/profile.dto.dart b/apps/flutter/account_core/lib/models/profile.dto.dart new file mode 100644 index 000000000..eff685122 --- /dev/null +++ b/apps/flutter/account_core/lib/models/profile.dto.dart @@ -0,0 +1,89 @@ +import 'package:core/models/abp.dto.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'profile.dto.g.dart'; + +@JsonSerializable() +class ProfileDto extends ExtensibleObject { + ProfileDto({ + this.userName, + this.email, + this.name, + this.surname, + this.phoneNumber, + this.concurrencyStamp, + this.isExternal = false, + this.hasPassword = false, + super.extraProperties, + }); + String? userName; + String? email; + String? name; + String? surname; + String? phoneNumber; + bool isExternal; + bool hasPassword; + String? concurrencyStamp; + + factory ProfileDto.fromJson(Map json) => _$ProfileDtoFromJson(json); + + @override + Map toJson() => _$ProfileDtoToJson(this); +} + +@JsonSerializable() +class ChangePasswordInput { + ChangePasswordInput({ + this.currentPassword, + required this.newPassword, + }); + String? currentPassword; + String newPassword; + + factory ChangePasswordInput.fromJson(Map json) => _$ChangePasswordInputFromJson(json); + Map toJson() => _$ChangePasswordInputToJson(this); +} + +@JsonSerializable() +class RegisterDto extends ExtensibleObject { + RegisterDto({ + required this.userName, + required this.emailAddress, + required this.password, + this.appName = 'abp-flutter', + super.extraProperties, + }); + String userName; + String emailAddress; + String password; + String appName; + + factory RegisterDto.fromJson(Map json) => _$RegisterDtoFromJson(json); + + @override + Map toJson() => _$RegisterDtoToJson(this); +} + +@JsonSerializable() +class UpdateProfileDto extends ExtensibleObject { + UpdateProfileDto({ + this.userName, + this.email, + this.name, + this.surname, + this.phoneNumber, + this.concurrencyStamp, + super.extraProperties, + }); + String? userName; + String? email; + String? name; + String? surname; + String? phoneNumber; + String? concurrencyStamp; + + factory UpdateProfileDto.fromJson(Map json) => _$UpdateProfileDtoFromJson(json); + + @override + Map toJson() => _$UpdateProfileDtoToJson(this); +} \ No newline at end of file diff --git a/apps/flutter/account_core/lib/models/profile.dto.g.dart b/apps/flutter/account_core/lib/models/profile.dto.g.dart new file mode 100644 index 000000000..1054ea9b8 --- /dev/null +++ b/apps/flutter/account_core/lib/models/profile.dto.g.dart @@ -0,0 +1,84 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'profile.dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProfileDto _$ProfileDtoFromJson(Map json) => ProfileDto( + userName: json['userName'] as String?, + email: json['email'] as String?, + name: json['name'] as String?, + surname: json['surname'] as String?, + phoneNumber: json['phoneNumber'] as String?, + concurrencyStamp: json['concurrencyStamp'] as String?, + isExternal: json['isExternal'] as bool? ?? false, + hasPassword: json['hasPassword'] as bool? ?? false, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ProfileDtoToJson(ProfileDto instance) => + { + 'extraProperties': instance.extraProperties, + 'userName': instance.userName, + 'email': instance.email, + 'name': instance.name, + 'surname': instance.surname, + 'phoneNumber': instance.phoneNumber, + 'isExternal': instance.isExternal, + 'hasPassword': instance.hasPassword, + 'concurrencyStamp': instance.concurrencyStamp, + }; + +ChangePasswordInput _$ChangePasswordInputFromJson(Map json) => + ChangePasswordInput( + currentPassword: json['currentPassword'] as String?, + newPassword: json['newPassword'] as String, + ); + +Map _$ChangePasswordInputToJson( + ChangePasswordInput instance) => + { + 'currentPassword': instance.currentPassword, + 'newPassword': instance.newPassword, + }; + +RegisterDto _$RegisterDtoFromJson(Map json) => RegisterDto( + userName: json['userName'] as String, + emailAddress: json['emailAddress'] as String, + password: json['password'] as String, + appName: json['appName'] as String? ?? 'abp-flutter', + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$RegisterDtoToJson(RegisterDto instance) => + { + 'extraProperties': instance.extraProperties, + 'userName': instance.userName, + 'emailAddress': instance.emailAddress, + 'password': instance.password, + 'appName': instance.appName, + }; + +UpdateProfileDto _$UpdateProfileDtoFromJson(Map json) => + UpdateProfileDto( + userName: json['userName'] as String?, + email: json['email'] as String?, + name: json['name'] as String?, + surname: json['surname'] as String?, + phoneNumber: json['phoneNumber'] as String?, + concurrencyStamp: json['concurrencyStamp'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$UpdateProfileDtoToJson(UpdateProfileDto instance) => + { + 'extraProperties': instance.extraProperties, + 'userName': instance.userName, + 'email': instance.email, + 'name': instance.name, + 'surname': instance.surname, + 'phoneNumber': instance.phoneNumber, + 'concurrencyStamp': instance.concurrencyStamp, + }; diff --git a/apps/flutter/account_core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/account_core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/account_core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.h b/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/apps/flutter/account_core/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/account_core/linux/flutter/generated_plugins.cmake b/apps/flutter/account_core/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/apps/flutter/account_core/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/apps/flutter/account_core/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/apps/flutter/account_core/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 000000000..2f8ae4c3f --- /dev/null +++ b/apps/flutter/account_core/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\account_core +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/account_core/macos/Flutter/ephemeral/flutter_export_environment.sh b/apps/flutter/account_core/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100644 index 000000000..25b6fd9aa --- /dev/null +++ b/apps/flutter/account_core/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\account_core" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/account_core/pubspec.yaml b/apps/flutter/account_core/pubspec.yaml new file mode 100644 index 000000000..a82a07d8d --- /dev/null +++ b/apps/flutter/account_core/pubspec.yaml @@ -0,0 +1,62 @@ +name: account_core +description: A new Flutter package project. +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: '>=3.0.5 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + + core: + path: '../core' + json_annotation: ^4.8.1 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + + build_runner: ^2.4.5 + json_serializable: ^6.7.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.cc b/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.h b/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/apps/flutter/account_core/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/account_core/windows/flutter/generated_plugins.cmake b/apps/flutter/account_core/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/apps/flutter/account_core/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/apps/flutter/components/.flutter-plugins b/apps/flutter/components/.flutter-plugins index 48fac27e8..59e378d87 100644 --- a/apps/flutter/components/.flutter-plugins +++ b/apps/flutter/components/.flutter-plugins @@ -1,6 +1,6 @@ # This is a generated file; do not edit or check into version control. -path_provider=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ -path_provider_android=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ -path_provider_foundation=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ -path_provider_linux=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ -path_provider_windows=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ diff --git a/apps/flutter/components/.flutter-plugins-dependencies b/apps/flutter/components/.flutter-plugins-dependencies index 419cef769..42a95a946 100644 --- a/apps/flutter/components/.flutter-plugins-dependencies +++ b/apps/flutter/components/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-16 10:47:15.025132","version":"3.10.5"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-17 09:32:19.079179","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/components/android/local.properties b/apps/flutter/components/android/local.properties index 60b1ce328..1a3be4ff1 100644 --- a/apps/flutter/components/android/local.properties +++ b/apps/flutter/components/android/local.properties @@ -1,2 +1,2 @@ -sdk.dir=%UserProfile%\\AppData\\Local\\Android\\sdk +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/components/lib/components.module.dart b/apps/flutter/components/lib/components.module.dart new file mode 100644 index 000000000..3422b74c3 --- /dev/null +++ b/apps/flutter/components/lib/components.module.dart @@ -0,0 +1,7 @@ +import 'package:core/core.module.dart'; +import 'package:core/modularity/index.dart'; + +class ComponentsModule extends Module { + @override + List get dependencies => [CoreModule()]; +} \ No newline at end of file diff --git a/apps/flutter/components/lib/config/avatar.config.dart b/apps/flutter/components/lib/config/avatar.config.dart deleted file mode 100644 index 9f90a963e..000000000 --- a/apps/flutter/components/lib/config/avatar.config.dart +++ /dev/null @@ -1,3 +0,0 @@ -class AvatarConfig { - static String baseUrl = 'http://127.0.0.1:8080/blob/avatars'; -} \ No newline at end of file diff --git a/apps/flutter/components/lib/config/index.dart b/apps/flutter/components/lib/config/index.dart deleted file mode 100644 index 606c6f290..000000000 --- a/apps/flutter/components/lib/config/index.dart +++ /dev/null @@ -1 +0,0 @@ -export 'avatar.config.dart'; \ No newline at end of file diff --git a/apps/flutter/components/lib/index.dart b/apps/flutter/components/lib/index.dart index e6349e001..f82bcfbc1 100644 --- a/apps/flutter/components/lib/index.dart +++ b/apps/flutter/components/lib/index.dart @@ -1,3 +1,3 @@ -export './config/index.dart'; export './pages/index.dart'; -export './widgets/index.dart'; \ No newline at end of file +export './widgets/index.dart'; +export 'components.module.dart'; \ No newline at end of file diff --git a/apps/flutter/components/lib/pages/index.dart b/apps/flutter/components/lib/pages/index.dart index 0137a90d1..41e561549 100644 --- a/apps/flutter/components/lib/pages/index.dart +++ b/apps/flutter/components/lib/pages/index.dart @@ -1 +1,2 @@ -export 'page.base.dart'; \ No newline at end of file +export 'page.base.dart'; +export 'widget.base.dart'; \ No newline at end of file diff --git a/apps/flutter/components/lib/pages/widget.base.dart b/apps/flutter/components/lib/pages/widget.base.dart new file mode 100644 index 000000000..a72f9ad59 --- /dev/null +++ b/apps/flutter/components/lib/pages/widget.base.dart @@ -0,0 +1,8 @@ +import 'package:core/dependency/index.dart'; +import 'package:get/get.dart'; + +abstract class BaseWidget extends GetWidget { + const BaseWidget({super.key}); + + Bloc get bloc => Injector.instance.get(tag: tag); +} \ No newline at end of file diff --git a/apps/flutter/components/lib/widgets/avatar/index.dart b/apps/flutter/components/lib/widgets/avatar/index.dart index 3d01c6c95..217cc59c2 100644 --- a/apps/flutter/components/lib/widgets/avatar/index.dart +++ b/apps/flutter/components/lib/widgets/avatar/index.dart @@ -1,6 +1,5 @@ import 'package:core/utils/string.extensions.dart'; import 'package:flutter/material.dart'; -import 'package:components/config/avatar.config.dart'; class Avatar extends StatelessWidget { const Avatar({ @@ -15,27 +14,13 @@ class Avatar extends StatelessWidget { final String? hintText; final String? schema; final String? takeToken; - - String get avatarUrl { - var formatUrl = url ?? ''; - if (!formatUrl.isNullOrWhiteSpace()) { - var urlSchema = schema ?? AvatarConfig.baseUrl; - if (!formatUrl.startsWith(urlSchema)) { - formatUrl = "$urlSchema$formatUrl"; - } - } - if (!takeToken.isNullOrWhiteSpace()) { - formatUrl += "?access_token=$takeToken"; - } - return formatUrl; - } @override Widget build(BuildContext context) { return CircleAvatar( child: !url.isNullOrWhiteSpace() ? CircleAvatar( - backgroundImage: NetworkImage(avatarUrl), + backgroundImage: NetworkImage(url!), ) : Text(!hintText.isNullOrWhiteSpace() && hintText!.length > 3 ? hintText!.substring(0, 3) : hintText ?? 'A', style: const TextStyle( diff --git a/apps/flutter/components/lib/widgets/back-to-top/index.dart b/apps/flutter/components/lib/widgets/back-to-top/index.dart new file mode 100644 index 000000000..55b7fda76 --- /dev/null +++ b/apps/flutter/components/lib/widgets/back-to-top/index.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; + +class BackToTop extends StatefulWidget { + const BackToTop({ + super.key, + required this.controller, + this.bottom, + }); + + final double? bottom; + final ScrollController controller; + + @override + State createState() => _BackToTopState(); + +} + +class _BackToTopState extends State { + bool shown = false; + + @override + void initState() { + super.initState(); + widget.controller.addListener(isScroll); + } + + void isScroll() { + final bool toShow = widget.controller.offset > MediaQuery.of(context).size.height / 2; + if (toShow ^ shown) { + setState(() { + shown = toShow; + }); + } + } + + @override + Widget build(BuildContext context) { + return Positioned( + bottom: MediaQuery.of(context).padding.bottom + (widget.bottom ?? 40), + right: 20, + child: Offstage( + offstage: !shown, + child: GestureDetector( + onTap: () { + widget.controller.animateTo(0, + duration: const Duration(milliseconds: 200), + curve: Curves.easeIn); + }, + child: Container( + height: 48, + width: 48, + alignment: const Alignment(0, 0), + decoration: BoxDecoration( + color: Theme.of(context).highlightColor, + borderRadius: const BorderRadius.all(Radius.circular(20)), + boxShadow: [ + BoxShadow( + color: const Color(0xFF000000).withOpacity(0.1), + blurRadius: 4, + spreadRadius: 0), + ]), + child: Column( + children: [ + Container( + margin: const EdgeInsets.only(top: 4), + child: Icon( + Icons.vertical_align_top, + size: 20, + color: Theme.of(context).hintColor, + ), + ), + Container( + margin: const EdgeInsets.only(top: 0), + child: const Text( + 'Top', + //style: TextStyle(fontSize: 10, color: Color(0xFFA1A6AA)), + ), + ) + ], + ) + ), + ), + ) + ); + } +} \ No newline at end of file diff --git a/apps/flutter/components/lib/widgets/index.dart b/apps/flutter/components/lib/widgets/index.dart index 2683ea74b..a3d62f746 100644 --- a/apps/flutter/components/lib/widgets/index.dart +++ b/apps/flutter/components/lib/widgets/index.dart @@ -1,4 +1,5 @@ export 'avatar/index.dart'; export 'action-button/index.dart'; +export 'back-to-top/index.dart'; export 'bottom-button/index.dart'; export 'empty/index.dart'; \ No newline at end of file diff --git a/apps/flutter/components/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/components/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/components/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/components/pubspec.yaml b/apps/flutter/components/pubspec.yaml index fd7e4a6ed..8cda86e7e 100644 --- a/apps/flutter/components/pubspec.yaml +++ b/apps/flutter/components/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: sdk: flutter core: path: '../core' - get: + get: ^4.6.5 dev_dependencies: flutter_test: diff --git a/apps/flutter/core/.flutter-plugins b/apps/flutter/core/.flutter-plugins index 48fac27e8..59e378d87 100644 --- a/apps/flutter/core/.flutter-plugins +++ b/apps/flutter/core/.flutter-plugins @@ -1,6 +1,6 @@ # This is a generated file; do not edit or check into version control. -path_provider=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ -path_provider_android=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ -path_provider_foundation=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ -path_provider_linux=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ -path_provider_windows=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.3\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ diff --git a/apps/flutter/core/.flutter-plugins-dependencies b/apps/flutter/core/.flutter-plugins-dependencies index f3f5d8430..b668bb06f 100644 --- a/apps/flutter/core/.flutter-plugins-dependencies +++ b/apps/flutter/core/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-16 08:23:33.451996","version":"3.10.5"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.3\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-19 11:21:40.892667","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/core/android/local.properties b/apps/flutter/core/android/local.properties index 60b1ce328..1a3be4ff1 100644 --- a/apps/flutter/core/android/local.properties +++ b/apps/flutter/core/android/local.properties @@ -1,2 +1,2 @@ -sdk.dir=%UserProfile%\\AppData\\Local\\Android\\sdk +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/core/lib/abstracts/index.dart b/apps/flutter/core/lib/abstracts/index.dart index 3ac25e682..909f662f2 100644 --- a/apps/flutter/core/lib/abstracts/index.dart +++ b/apps/flutter/core/lib/abstracts/index.dart @@ -1,2 +1,3 @@ export 'copy.with.dart'; -export 'logging.dart'; \ No newline at end of file +export 'logging.dart'; +export 'signalr.service.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/abstracts/signalr.service.dart b/apps/flutter/core/lib/abstracts/signalr.service.dart new file mode 100644 index 000000000..1951157b3 --- /dev/null +++ b/apps/flutter/core/lib/abstracts/signalr.service.dart @@ -0,0 +1,84 @@ +import 'dart:async'; + +import 'package:core/models/common.dart'; +import 'package:core/utils/logging.dart'; + +abstract class SignalrService { + + Future? start(); + + Future stop(); + + StreamSubscription onClose(Function(Exception?) listen, { bool Function(Exception?)? filter}); + + StreamSubscription onReconnecting(Function(Exception?) listen, { bool Function(Exception?)? filter}); + + StreamSubscription onReconnected(Function(String?) listen, { bool Function(String?)? filter}); + + Stream subscribe(String methodName); + + void unsubscribe(String methodName); + + Future send(String methodName, { List? args }); + + Future invoke(String methodName, { List? args }); +} + +class NullSignalrService extends SignalrService { + @override + Future invoke(String methodName, {List? args}) { + logger.warn('signalr - invoke method not implemented!'); + return Future.value(); + } + + @override + StreamSubscription onClose(Function(Exception? p1) listen, {bool Function(Exception? p1)? filter}) { + logger.warn('signalr - onClose method not implemented!'); + Exception? nullValue; + return Stream.value(nullValue).listen(logger.debug); + } + + @override + StreamSubscription onReconnected(Function(String? p1) listen, {bool Function(String? p1)? filter}) { + logger.warn('signalr - onReconnected method not implemented!'); + String? nullValue; + return Stream.value(nullValue).listen(logger.debug); + } + + @override + StreamSubscription onReconnecting(Function(Exception? p1) listen, {bool Function(Exception? p1)? filter}) { + logger.warn('signalr - onReconnecting method not implemented!'); + Exception? nullValue; + return Stream.value(nullValue).listen(logger.debug); + } + + @override + Future send(String methodName, {List? args}) { + logger.warn('signalr - send method not implemented!'); + return Future.value(); + } + + @override + Future? start() { + logger.warn('signalr - start method not implemented!'); + return Future.value(); + } + + @override + Future stop() { + logger.warn('signalr - stop method not implemented!'); + return Future.value(); + } + + @override + Stream subscribe(String methodName) { + logger.warn('signalr - subscribe method not implemented!'); + return Stream.value(SignalrMessage(methodName, [])); + } + + @override + void unsubscribe(String methodName) { + logger.warn('signalr - unsubscribe method not implemented!'); + } + +} \ No newline at end of file diff --git a/apps/flutter/core/lib/config/env.config.dart b/apps/flutter/core/lib/config/env.config.dart deleted file mode 100644 index 3dfa1aeb8..000000000 --- a/apps/flutter/core/lib/config/env.config.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter_app_environment/flutter_app_environment.dart' as envlib; - -part 'env.config.g.dart'; - -@JsonSerializable(createToJson: false) -class EnvConfig { - EnvConfig({ - required this.clientId, - this.clientSecret, - required this.authority, - required this.baseUrl, - this.uploadFilesUrl, - this.staticFilesUrl, - this.tenantKey = '__tenant', - this.defaultLanguage = 'en', - this.notifications, - }); - String clientId; - String? clientSecret; - String authority; - String baseUrl; - String? uploadFilesUrl; - String? staticFilesUrl; - String? tenantKey; - String? defaultLanguage; - NotificationConfig? notifications; - - factory EnvConfig.fromJson(Map json) => _$EnvConfigFromJson(json); -} - -@JsonSerializable(createToJson: false) -class NotificationConfig { - NotificationConfig({ - this.android, - this.darwin, - this.linux, - }); - AndroidNotification? android; - DarwinNotification? darwin; - LinuxNotification? linux; - - factory NotificationConfig.fromJson(Map json) => _$NotificationConfigFromJson(json); -} - -@JsonSerializable(createToJson: false) -class LinuxNotification { - LinuxNotification({ - required this.defaultActionName, - }); - String defaultActionName; - - factory LinuxNotification.fromJson(Map json) => _$LinuxNotificationFromJson(json); -} - -@JsonSerializable(createToJson: false) -class AndroidNotification { - AndroidNotification({ - required this.channelId, - required this.channelName, - this.channelDescription, - }); - String channelId; - String channelName; - String? channelDescription; - - factory AndroidNotification.fromJson(Map json) => _$AndroidNotificationFromJson(json); -} - -@JsonSerializable(createToJson: false) -class DarwinNotification { - DarwinNotification(); - - factory DarwinNotification.fromJson(Map json) => _$DarwinNotificationFromJson(json); -} - -enum Env { - development('DEV', 'Development'), - profile('PROF', 'Profile'), - production('PROD', 'Production'); - - final String name; - final String value; - const Env(this.name, this.value); - -} - -class Environment { - static Future initAsync() async { - var envType = envlib.EnvironmentType.development; - if (kReleaseMode) { - envType = envlib.EnvironmentType.production; - } else if (kProfileMode) { - envType = envlib.EnvironmentType.test; - } - - await envlib.Environment.initFromJson( - environmentType: envType, - fromJson: EnvConfig.fromJson, - ); - - Environment.current = envlib.Environment.instance().config; - } - - static late EnvConfig current; -} diff --git a/apps/flutter/core/lib/config/env.config.g.dart b/apps/flutter/core/lib/config/env.config.g.dart deleted file mode 100644 index 3db6ffc35..000000000 --- a/apps/flutter/core/lib/config/env.config.g.dart +++ /dev/null @@ -1,51 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'env.config.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -EnvConfig _$EnvConfigFromJson(Map json) => EnvConfig( - clientId: json['clientId'] as String, - clientSecret: json['clientSecret'] as String?, - authority: json['authority'] as String, - baseUrl: json['baseUrl'] as String, - uploadFilesUrl: json['uploadFilesUrl'] as String?, - staticFilesUrl: json['staticFilesUrl'] as String?, - tenantKey: json['tenantKey'] as String? ?? '__tenant', - defaultLanguage: json['defaultLanguage'] as String? ?? 'en', - notifications: json['notifications'] == null - ? null - : NotificationConfig.fromJson( - json['notifications'] as Map), - ); - -NotificationConfig _$NotificationConfigFromJson(Map json) => - NotificationConfig( - android: json['android'] == null - ? null - : AndroidNotification.fromJson( - json['android'] as Map), - darwin: json['darwin'] == null - ? null - : DarwinNotification.fromJson(json['darwin'] as Map), - linux: json['linux'] == null - ? null - : LinuxNotification.fromJson(json['linux'] as Map), - ); - -LinuxNotification _$LinuxNotificationFromJson(Map json) => - LinuxNotification( - defaultActionName: json['defaultActionName'] as String, - ); - -AndroidNotification _$AndroidNotificationFromJson(Map json) => - AndroidNotification( - channelId: json['channelId'] as String, - channelName: json['channelName'] as String, - channelDescription: json['channelDescription'] as String?, - ); - -DarwinNotification _$DarwinNotificationFromJson(Map json) => - DarwinNotification(); diff --git a/apps/flutter/core/lib/config/index.dart b/apps/flutter/core/lib/config/index.dart deleted file mode 100644 index dcea24ea1..000000000 --- a/apps/flutter/core/lib/config/index.dart +++ /dev/null @@ -1 +0,0 @@ -export 'env.config.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/core.module.dart b/apps/flutter/core/lib/core.module.dart index f2d8dadfc..3c92ceb75 100644 --- a/apps/flutter/core/lib/core.module.dart +++ b/apps/flutter/core/lib/core.module.dart @@ -1,35 +1,34 @@ -import 'package:core/dependency/injector.dart'; import 'package:core/modularity/module.dart'; import 'package:core/services/index.dart'; import 'proxy/index.dart'; class CoreModule extends Module { - @override Future configureServicesAsync() async { - await injectAsync(() async { + await injectAsync((injector) async { if (await GetxStorageService.init()) { - return GetxStorageService(); + return GetxStorageService(injector); } - return StorageService(); + return StorageService(injector); }, permanent: true); await super.configureServicesAsync(); } @override void configureServices() { - inject(Injector.instance); - inject(this); - inject(ConfigStateService(), permanent: true); - inject(ThemeService(), permanent: true); + inject(this, permanent: true); + inject(EnvironmentService(injector), permanent: true); + inject(ConfigStateService(injector), permanent: true); + inject(ThemeService(injector), permanent: true); + inject(ErrorReporterService(), permanent: true); - lazyInject(() => SessionService(), fenix: true); - lazyInject(() => SubscriptionService(), fenix: true); - lazyInject(() => LanguageService(), fenix: true); - lazyInject(() => LocalizationService(), fenix: true); - lazyInject(() => AbpTenantService(), fenix: true); - lazyInject(() => AbpApiDefinitionService(), fenix: true); - lazyInject(() => AbpApplicationLocalizationService(), fenix: true); - lazyInject(() => AbpApplicationConfigurationService(), fenix: true); + lazyInject((injector) => SubscriptionService(injector)); + lazyInject((injector) => SessionService(injector), fenix: true); + lazyInject((injector) => LanguageService(injector), fenix: true); + lazyInject((injector) => LocalizationService(injector), fenix: true); + lazyInject((injector) => AbpTenantService(injector), fenix: true); + lazyInject((injector) => AbpApiDefinitionService(injector), fenix: true); + lazyInject((injector) => AbpApplicationLocalizationService(injector), fenix: true); + lazyInject((injector) => AbpApplicationConfigurationService(injector), fenix: true); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/dependency/index.dart b/apps/flutter/core/lib/dependency/index.dart index 9d253260d..698b82eb5 100644 --- a/apps/flutter/core/lib/dependency/index.dart +++ b/apps/flutter/core/lib/dependency/index.dart @@ -1 +1,2 @@ -export 'injector.dart'; \ No newline at end of file +export 'injector.dart'; +export 'injector.builder.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/dependency/injector.builder.dart b/apps/flutter/core/lib/dependency/injector.builder.dart new file mode 100644 index 000000000..add943143 --- /dev/null +++ b/apps/flutter/core/lib/dependency/injector.builder.dart @@ -0,0 +1,5 @@ +import 'injector.dart'; + +typedef InjectorBuilderFactory = T Function(Injector injector); + +typedef AsyncInjectorBuilderFactory = Future Function(Injector injector); diff --git a/apps/flutter/core/lib/dependency/injector.dart b/apps/flutter/core/lib/dependency/injector.dart index 734f9a745..bdaf0cc30 100644 --- a/apps/flutter/core/lib/dependency/injector.dart +++ b/apps/flutter/core/lib/dependency/injector.dart @@ -1,5 +1,9 @@ import 'package:get/get.dart'; +import 'injector.builder.dart'; + +final Injector injector = Injector.instance; + class Injector { factory Injector() => _getInstance ??= const Injector._(); @@ -16,30 +20,32 @@ class Injector { { String? tag, bool permanent = false, - InstanceBuilderCallback? builder, - }) => Get.put(dependency, tag: tag, permanent: permanent, builder: builder); + InjectorBuilderFactory? builder, + }) => Get.put(dependency, tag: tag, permanent: permanent, builder: () { + return builder != null ? builder(get()) : dependency; + }); void create( - InstanceBuilderCallback builder, + InjectorBuilderFactory builder, { String? tag, bool permanent = true, } - ) => Get.create(builder, tag: tag, permanent: permanent); + ) => Get.create(() => builder(get()), tag: tag, permanent: permanent); void lazyInject( - InstanceBuilderCallback builder, + InjectorBuilderFactory builder, { String? tag, bool fenix = false, - }) => Get.lazyPut(builder, tag: tag, fenix: fenix); + }) => Get.lazyPut(() => builder(get()), tag: tag, fenix: fenix); Future injectAsync( - AsyncInstanceBuilderCallback builder, + AsyncInjectorBuilderFactory builder, { String? tag, bool permanent = false, - }) => Get.putAsync(builder, tag: tag, permanent: permanent); + }) => Get.putAsync(() => builder(get()), tag: tag, permanent: permanent); bool isInjected({String? tag}) => Get.isRegistered(tag: tag); } \ No newline at end of file diff --git a/apps/flutter/core/lib/index.dart b/apps/flutter/core/lib/index.dart index ec10ee99a..7abea850a 100644 --- a/apps/flutter/core/lib/index.dart +++ b/apps/flutter/core/lib/index.dart @@ -1,5 +1,4 @@ export './abstracts/index.dart'; -export './config/index.dart'; export './dependency/index.dart'; export './interceptors/index.dart'; export './middlewares/index.dart'; diff --git a/apps/flutter/account/lib/interceptors/oauth.api.interceptor.dart b/apps/flutter/core/lib/interceptors/api.authorization.interceptor.dart similarity index 95% rename from apps/flutter/account/lib/interceptors/oauth.api.interceptor.dart rename to apps/flutter/core/lib/interceptors/api.authorization.interceptor.dart index ed7cecf07..0ae116a4e 100644 --- a/apps/flutter/account/lib/interceptors/oauth.api.interceptor.dart +++ b/apps/flutter/core/lib/interceptors/api.authorization.interceptor.dart @@ -7,7 +7,7 @@ import 'package:core/tokens/http.token.dart'; import 'package:core/utils/string.extensions.dart'; import 'package:dio/dio.dart'; -class OAuthApiInterceptor extends Interceptor { +class ApiAuthorizationInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { if (!options.extra.containsKey(HttpTokens.ignoreToken)) { @@ -33,9 +33,9 @@ class OAuthApiInterceptor extends Interceptor { var authService = AuthService.to; authService.refreshToken(RefreshTokenParams(token.refreshToken!)) .then((value) { - SessionService.to.refreshToken(value); + //SessionService.to.setToken(value); //err.requestOptions - RestService.to.request( + RestService.to.dio.request( err.requestOptions.path, data: err.requestOptions.data, queryParameters: err.requestOptions.queryParameters, diff --git a/apps/flutter/core/lib/interceptors/api.logger.interceptor.dart b/apps/flutter/core/lib/interceptors/api.logger.interceptor.dart index 979745a7b..d5c9bb373 100644 --- a/apps/flutter/core/lib/interceptors/api.logger.interceptor.dart +++ b/apps/flutter/core/lib/interceptors/api.logger.interceptor.dart @@ -16,7 +16,7 @@ class LoggerInterceptor extends Interceptor { @override void onError(DioException err, ErrorInterceptorHandler handler) { - logger.debug('网络请求错误', err, err.stackTrace); + logger.error('网络请求错误', err, err.stackTrace); return handler.next(err); } } diff --git a/apps/flutter/core/lib/interceptors/api.wrapper.result.interceptor.dart b/apps/flutter/core/lib/interceptors/api.wrapper.result.interceptor.dart index 0ad9c2e1b..7c8345cc2 100644 --- a/apps/flutter/core/lib/interceptors/api.wrapper.result.interceptor.dart +++ b/apps/flutter/core/lib/interceptors/api.wrapper.result.interceptor.dart @@ -1,5 +1,6 @@ import 'package:core/models/wrapper.dart'; import 'package:dio/dio.dart'; +import 'package:get/get.dart' show Trans; class WrapperResultInterceptor extends Interceptor { @override @@ -10,7 +11,7 @@ class WrapperResultInterceptor extends Interceptor { requestOptions: response.requestOptions, response: response, type: DioExceptionType.badResponse, - message: '请求出错, 请稍后再试!')); + message: 'Prompt:ApiRequestFailed'.tr)); return; } var result = Wrapper.fromJson(response.data!); diff --git a/apps/flutter/core/lib/interceptors/index.dart b/apps/flutter/core/lib/interceptors/index.dart index 90e0277fe..32ed3a605 100644 --- a/apps/flutter/core/lib/interceptors/index.dart +++ b/apps/flutter/core/lib/interceptors/index.dart @@ -1,3 +1,4 @@ export 'api.abp.wrapper.error.interceptor.dart'; +export 'api.authorization.interceptor.dart'; export 'api.wrapper.result.interceptor.dart'; export 'api.logger.interceptor.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/models/abp.dto.dart b/apps/flutter/core/lib/models/abp.dto.dart index e218ffe54..a79248933 100644 --- a/apps/flutter/core/lib/models/abp.dto.dart +++ b/apps/flutter/core/lib/models/abp.dto.dart @@ -1,3 +1,8 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'abp.dto.g.dart'; + +@JsonSerializable() class LocalizableStringInfo { LocalizableStringInfo({ required this.resourceName, @@ -8,135 +13,38 @@ class LocalizableStringInfo { String name; Map? values; - factory LocalizableStringInfo.fromJson(Map json) => - LocalizableStringInfo( - resourceName: json['resourceName'] as String, - name: json['name'] as String, - values: json['values'] as Map?, - ); - Map toJson() => { - 'resourceName': resourceName, - 'name': name, - 'values': values, - }; -} - - -class ExtraPropertyDictionary implements Map { - ExtraPropertyDictionary({ - Map? map - }) { - _innerMap = map ?? {}; - } - late Map _innerMap = {}; - @override - operator [](Object? key) { - return _innerMap[key]; - } - - @override - void operator []=(String key, value) { - _innerMap[key] = value; - } - - @override - void addAll(Map other) { - _innerMap.addAll(other); - } - - @override - void addEntries(Iterable> newEntries) { - _innerMap.addEntries(newEntries); - } - - @override - Map cast() { - return _innerMap.cast(); - } - - @override - void clear() { - _innerMap.clear(); - } - - @override - bool containsKey(Object? key) { - return _innerMap.containsKey(key); - } - - @override - bool containsValue(Object? value) { - return _innerMap.containsValue(value); - } - - @override - Iterable> get entries => _innerMap.entries; - - @override - void forEach(void Function(String key, dynamic value) action) { - _innerMap.forEach(action); - } - - @override - bool get isEmpty => _innerMap.isEmpty; - - @override - bool get isNotEmpty => _innerMap.isNotEmpty; - - @override - Iterable get keys => _innerMap.keys; - - @override - int get length => _innerMap.length; - - @override - Map map(MapEntry Function(String key, dynamic value) convert) { - return _innerMap.map(convert); - } - - @override - putIfAbsent(String key, Function() ifAbsent) { - return _innerMap.putIfAbsent(key, ifAbsent); - } - - @override - remove(Object? key) { - return _innerMap.remove(key); - } - - @override - void removeWhere(bool Function(String key, dynamic value) test) { - _innerMap.removeWhere(test); - } - - @override - update(String key, Function(dynamic value) update, {Function()? ifAbsent}) { - return _innerMap.update(key, update, ifAbsent: ifAbsent); - } - - @override - void updateAll(Function(String key, dynamic value) update) { - _innerMap.updateAll(update); - } - - @override - Iterable get values => _innerMap.values; + factory LocalizableStringInfo.fromJson(Map json) => _$LocalizableStringInfoFromJson(json); + Map toJson() => _$LocalizableStringInfoToJson(this); } +@JsonSerializable() class ExtensibleObject { ExtensibleObject({ this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensibleObject.fromJson(Map json) => _$ExtensibleObjectFromJson(json); + Map toJson() => _$ExtensibleObjectToJson(this); } +@JsonSerializable(genericArgumentFactories: true) class EntityDto { EntityDto({ required this.id, }); TPrimaryKey id; + + factory EntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$EntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$EntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class CreationAuditedEntityDto extends EntityDto { CreationAuditedEntityDto({ required super.id, @@ -145,8 +53,18 @@ class CreationAuditedEntityDto extends EntityDto { }); DateTime creationTime; String? creatorId; + + factory CreationAuditedEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$CreationAuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$CreationAuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class CreationAuditedEntityWithUserDto extends CreationAuditedEntityDto { CreationAuditedEntityWithUserDto({ required super.id, @@ -155,8 +73,29 @@ class CreationAuditedEntityWithUserDto extends CreationAu super.creatorId, }); TUserDto creator; + + factory CreationAuditedEntityWithUserDto.fromJson( + Map json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$CreationAuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$CreationAuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } +@JsonSerializable(genericArgumentFactories: true) class AuditedEntityDto extends CreationAuditedEntityDto { AuditedEntityDto({ required super.id, @@ -167,8 +106,18 @@ class AuditedEntityDto extends CreationAuditedEntityDto json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$AuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$AuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class AuditedEntityWithUserDto extends AuditedEntityDto { AuditedEntityWithUserDto({ required super.id, @@ -181,8 +130,29 @@ class AuditedEntityWithUserDto extends AuditedEntityDto json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$AuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$AuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } +@JsonSerializable(genericArgumentFactories: true) class FullAuditedEntityDto extends AuditedEntityDto { FullAuditedEntityDto({ required super.id, @@ -197,8 +167,18 @@ class FullAuditedEntityDto extends AuditedEntityDto { bool isDeleted; String? deleterId; DateTime? deletionTime; + + factory FullAuditedEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$FullAuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$FullAuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class FullAuditedEntityWithUserDto extends FullAuditedEntityDto { FullAuditedEntityWithUserDto({ required super.id, @@ -216,35 +196,100 @@ class FullAuditedEntityWithUserDto extends FullAuditedEnt TUserDto creator; TUserDto lastModifier; TUserDto deleter; + + factory FullAuditedEntityWithUserDto.fromJson( + Map json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$FullAuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$FullAuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } -class ExtensibleEntityDto extends ExtensibleObject { +@JsonSerializable(genericArgumentFactories: true) +class ExtensibleEntityDto extends ExtensibleObject { ExtensibleEntityDto({ required this.id, + super.extraProperties, }); - TKey id; + TPrimaryKey id; + + factory ExtensibleEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$ExtensibleEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$ExtensibleEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleCreationAuditedEntityDto extends ExtensibleEntityDto { ExtensibleCreationAuditedEntityDto({ required super.id, required this.creationTime, this.creatorId, + super.extraProperties, }); DateTime creationTime; String? creatorId; + + factory ExtensibleCreationAuditedEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$ExtensibleCreationAuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$ExtensibleCreationAuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleCreationAuditedEntityWithUserDto extends ExtensibleCreationAuditedEntityDto { ExtensibleCreationAuditedEntityWithUserDto({ required super.id, required this.creator, required super.creationTime, super.creatorId, + super.extraProperties, }); TUserDto creator; + + factory ExtensibleCreationAuditedEntityWithUserDto.fromJson( + Map json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$ExtensibleCreationAuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$ExtensibleCreationAuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleAuditedEntityDto extends ExtensibleCreationAuditedEntityDto { ExtensibleAuditedEntityDto({ required super.id, @@ -252,11 +297,22 @@ class ExtensibleAuditedEntityDto extends ExtensibleCreationAuditedE super.creatorId, this.lastModificationTime, this.lastModifierId, + super.extraProperties, }); DateTime? lastModificationTime; String? lastModifierId; + + factory ExtensibleAuditedEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$ExtensibleAuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$ExtensibleAuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleAuditedEntityWithUserDto extends ExtensibleAuditedEntityDto { ExtensibleAuditedEntityWithUserDto({ required super.id, @@ -266,11 +322,33 @@ class ExtensibleAuditedEntityWithUserDto extends Extensib super.creatorId, super.lastModificationTime, super.lastModifierId, + super.extraProperties, }); TUserDto creator; TUserDto lastModifier; + + factory ExtensibleAuditedEntityWithUserDto.fromJson( + Map json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$ExtensibleAuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$ExtensibleAuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleFullAuditedEntityDto extends ExtensibleAuditedEntityDto { ExtensibleFullAuditedEntityDto({ required super.id, @@ -281,12 +359,23 @@ class ExtensibleFullAuditedEntityDto extends ExtensibleAuditedEntit super.creatorId, super.lastModificationTime, super.lastModifierId, + super.extraProperties, }); bool isDeleted; String? deleterId; DateTime? deletionTime; + + factory ExtensibleFullAuditedEntityDto.fromJson( + Map json, + { TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey }) => + _$ExtensibleFullAuditedEntityDtoFromJson(json, fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey); + + @override + Map toJson({ Object? Function(TPrimaryKey value)? toJsonTPrimaryKey }) => + _$ExtensibleFullAuditedEntityDtoToJson(this, toJsonTPrimaryKey ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleFullAuditedEntityWithUserDto extends ExtensibleFullAuditedEntityDto { ExtensibleFullAuditedEntityWithUserDto({ required super.id, @@ -300,74 +389,157 @@ class ExtensibleFullAuditedEntityWithUserDto extends Exte super.creatorId, super.lastModificationTime, super.lastModifierId, + super.extraProperties, }); TUserDto creator; TUserDto lastModifier; TUserDto deleter; + + factory ExtensibleFullAuditedEntityWithUserDto.fromJson( + Map json, + { + TPrimaryKey Function(Object? json)? fromJsonTPrimaryKey, + TUserDto Function(Object? json)? fromJsonTUserDto, + }) => + _$ExtensibleFullAuditedEntityWithUserDtoFromJson(json, + fromJsonTPrimaryKey ?? (json) => json as TPrimaryKey, + fromJsonTUserDto ?? (json) => json as TUserDto); + + @override + Map toJson( + { + Object? Function(TPrimaryKey value)? toJsonTPrimaryKey, + Object? Function(TUserDto value)? toJsonTUserDto, + }) => + _$ExtensibleFullAuditedEntityWithUserDtoToJson(this, + toJsonTPrimaryKey ?? (instance) => instance, + toJsonTUserDto ?? (instance) => instance); } +@JsonSerializable(genericArgumentFactories: true) class ListResultDto { ListResultDto({ required this.items, }); List items; + + factory ListResultDto.fromJson( + Map json, + { T Function(Object? json)? fromJsonT }) => + _$ListResultDtoFromJson(json, fromJsonT ?? (json) => json as T); + + Map toJson({ Object? Function(T value)? toJsonT }) => + _$ListResultDtoToJson(this, toJsonT ?? (json) => json); } +@JsonSerializable() class LimitedResultRequestDto { LimitedResultRequestDto({ this.maxResultCount, }); int? maxResultCount = 10; + + factory LimitedResultRequestDto.fromJson(Map json) => _$LimitedResultRequestDtoFromJson(json); + + Map toJson() => _$LimitedResultRequestDtoToJson(this); } +@JsonSerializable() class ExtensibleLimitedResultRequestDto extends LimitedResultRequestDto { ExtensibleLimitedResultRequestDto({ super.maxResultCount, this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensibleLimitedResultRequestDto.fromJson(Map json) => _$ExtensibleLimitedResultRequestDtoFromJson(json); + + @override + Map toJson() => _$ExtensibleLimitedResultRequestDtoToJson(this); } +@JsonSerializable(genericArgumentFactories: true) class ExtensibleListResultDto extends ListResultDto { ExtensibleListResultDto({ required super.items, this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensibleListResultDto.fromJson( + Map json, + { T Function(Object? json)? fromJsonT }) => + _$ExtensibleListResultDtoFromJson(json, fromJsonT ?? (json) => json as T); + + @override + Map toJson({ Object? Function(T value)? toJsonT }) => + _$ExtensibleListResultDtoToJson(this, toJsonT ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class PagedResultDto extends ListResultDto { PagedResultDto({ required this.totalCount, required super.items, }); int totalCount; + + factory PagedResultDto.fromJson( + Map json, + { T Function(Object? json)? fromJsonT }) => + _$PagedResultDtoFromJson(json, fromJsonT ?? (json) => json as T); + + @override + Map toJson({ Object? Function(T value)? toJsonT }) => + _$PagedResultDtoToJson(this, toJsonT ?? (json) => json); } +@JsonSerializable(genericArgumentFactories: true) class ExtensiblePagedResultDto extends PagedResultDto { ExtensiblePagedResultDto({ required super.totalCount, required super.items, this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensiblePagedResultDto.fromJson( + Map json, + { T Function(Object? json)? fromJsonT }) => + _$ExtensiblePagedResultDtoFromJson(json, fromJsonT ?? (json) => json as T); + + @override + Map toJson({ Object? Function(T value)? toJsonT }) => + _$ExtensiblePagedResultDtoToJson(this, toJsonT ?? (json) => json); } +@JsonSerializable() class SortedResultRequest { SortedResultRequest({ this.sorting, }); String? sorting; + + factory SortedResultRequest.fromJson(Map json) => _$SortedResultRequestFromJson(json); + + Map toJson() => _$SortedResultRequestToJson(this); } +@JsonSerializable() class PagedResultRequestDto extends LimitedResultRequestDto { PagedResultRequestDto({ this.skipCount, super.maxResultCount, }); int? skipCount = 0; + + factory PagedResultRequestDto.fromJson(Map json) => _$PagedResultRequestDtoFromJson(json); + + @override + Map toJson() => _$PagedResultRequestDtoToJson(this); } +@JsonSerializable() class PagedAndSortedResultRequestDto extends PagedResultRequestDto { PagedAndSortedResultRequestDto({ super.skipCount, @@ -375,8 +547,14 @@ class PagedAndSortedResultRequestDto extends PagedResultRequestDto { this.sorting, }); String? sorting; + + factory PagedAndSortedResultRequestDto.fromJson(Map json) => _$PagedAndSortedResultRequestDtoFromJson(json); + + @override + Map toJson() => _$PagedAndSortedResultRequestDtoToJson(this); } +@JsonSerializable() class ExtensiblePagedAndSortedResultRequestDto extends PagedAndSortedResultRequestDto { ExtensiblePagedAndSortedResultRequestDto({ super.skipCount, @@ -384,14 +562,25 @@ class ExtensiblePagedAndSortedResultRequestDto extends PagedAndSortedResultReque super.sorting, this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensiblePagedAndSortedResultRequestDto.fromJson(Map json) => _$ExtensiblePagedAndSortedResultRequestDtoFromJson(json); + + @override + Map toJson() => _$ExtensiblePagedAndSortedResultRequestDtoToJson(this); } +@JsonSerializable() class ExtensiblePagedResultRequestDto extends PagedResultRequestDto { ExtensiblePagedResultRequestDto({ super.skipCount, super.maxResultCount, this.extraProperties, }); - ExtraPropertyDictionary? extraProperties; + Map? extraProperties; + + factory ExtensiblePagedResultRequestDto.fromJson(Map json) => _$ExtensiblePagedResultRequestDtoFromJson(json); + + @override + Map toJson() => _$ExtensiblePagedResultRequestDtoToJson(this); } diff --git a/apps/flutter/core/lib/models/abp.dto.g.dart b/apps/flutter/core/lib/models/abp.dto.g.dart new file mode 100644 index 000000000..3ccea1d33 --- /dev/null +++ b/apps/flutter/core/lib/models/abp.dto.g.dart @@ -0,0 +1,627 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'abp.dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LocalizableStringInfo _$LocalizableStringInfoFromJson( + Map json) => + LocalizableStringInfo( + resourceName: (json['resourceName'] ?? json['ResourceName']) as String, + name: (json['name'] ?? json['Name']) as String, + values: (json['values'] ?? json['Values']) as Map?, + ); + +Map _$LocalizableStringInfoToJson( + LocalizableStringInfo instance) => + { + 'resourceName': instance.resourceName, + 'name': instance.name, + 'values': instance.values, + }; + +ExtensibleObject _$ExtensibleObjectFromJson(Map json) => + ExtensibleObject( + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleObjectToJson(ExtensibleObject instance) => + { + 'extraProperties': instance.extraProperties, + }; + +EntityDto _$EntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + EntityDto( + id: fromJsonTPrimaryKey(json['id']), + ); + +Map _$EntityDtoToJson( + EntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + }; + +CreationAuditedEntityDto + _$CreationAuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + CreationAuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + ); + +Map _$CreationAuditedEntityDtoToJson( + CreationAuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + }; + +CreationAuditedEntityWithUserDto + _$CreationAuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + CreationAuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + ); + +Map + _$CreationAuditedEntityWithUserDtoToJson( + CreationAuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'creator': toJsonTUserDto(instance.creator), + }; + +AuditedEntityDto _$AuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + AuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + ); + +Map _$AuditedEntityDtoToJson( + AuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + }; + +AuditedEntityWithUserDto + _$AuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + AuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + lastModifier: fromJsonTUserDto(json['lastModifier']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + ); + +Map _$AuditedEntityWithUserDtoToJson( + AuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'creator': toJsonTUserDto(instance.creator), + 'lastModifier': toJsonTUserDto(instance.lastModifier), + }; + +FullAuditedEntityDto _$FullAuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + FullAuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + isDeleted: json['isDeleted'] as bool, + deleterId: json['deleterId'] as String?, + deletionTime: json['deletionTime'] == null + ? null + : DateTime.parse(json['deletionTime'] as String), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + ); + +Map _$FullAuditedEntityDtoToJson( + FullAuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'isDeleted': instance.isDeleted, + 'deleterId': instance.deleterId, + 'deletionTime': instance.deletionTime?.toIso8601String(), + }; + +FullAuditedEntityWithUserDto + _$FullAuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + FullAuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + lastModifier: fromJsonTUserDto(json['lastModifier']), + deleter: fromJsonTUserDto(json['deleter']), + isDeleted: json['isDeleted'] as bool, + deleterId: json['deleterId'] as String?, + deletionTime: json['deletionTime'] == null + ? null + : DateTime.parse(json['deletionTime'] as String), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + ); + +Map + _$FullAuditedEntityWithUserDtoToJson( + FullAuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': + instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'isDeleted': instance.isDeleted, + 'deleterId': instance.deleterId, + 'deletionTime': instance.deletionTime?.toIso8601String(), + 'creator': toJsonTUserDto(instance.creator), + 'lastModifier': toJsonTUserDto(instance.lastModifier), + 'deleter': toJsonTUserDto(instance.deleter), + }; + +ExtensibleEntityDto _$ExtensibleEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + ExtensibleEntityDto( + id: fromJsonTPrimaryKey(json['id']), + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleEntityDtoToJson( + ExtensibleEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + }; + +ExtensibleCreationAuditedEntityDto + _$ExtensibleCreationAuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + ExtensibleCreationAuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleCreationAuditedEntityDtoToJson( + ExtensibleCreationAuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + }; + +ExtensibleCreationAuditedEntityWithUserDto + _$ExtensibleCreationAuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + ExtensibleCreationAuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map + _$ExtensibleCreationAuditedEntityWithUserDtoToJson( + ExtensibleCreationAuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'creator': toJsonTUserDto(instance.creator), + }; + +ExtensibleAuditedEntityDto + _$ExtensibleAuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + ExtensibleAuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleAuditedEntityDtoToJson( + ExtensibleAuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + }; + +ExtensibleAuditedEntityWithUserDto + _$ExtensibleAuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + ExtensibleAuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + lastModifier: fromJsonTUserDto(json['lastModifier']), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map + _$ExtensibleAuditedEntityWithUserDtoToJson( + ExtensibleAuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': + instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'creator': toJsonTUserDto(instance.creator), + 'lastModifier': toJsonTUserDto(instance.lastModifier), + }; + +ExtensibleFullAuditedEntityDto + _$ExtensibleFullAuditedEntityDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, +) => + ExtensibleFullAuditedEntityDto( + id: fromJsonTPrimaryKey(json['id']), + isDeleted: json['isDeleted'] as bool, + deleterId: json['deleterId'] as String?, + deletionTime: json['deletionTime'] == null + ? null + : DateTime.parse(json['deletionTime'] as String), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleFullAuditedEntityDtoToJson( + ExtensibleFullAuditedEntityDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'isDeleted': instance.isDeleted, + 'deleterId': instance.deleterId, + 'deletionTime': instance.deletionTime?.toIso8601String(), + }; + +ExtensibleFullAuditedEntityWithUserDto + _$ExtensibleFullAuditedEntityWithUserDtoFromJson( + Map json, + TPrimaryKey Function(Object? json) fromJsonTPrimaryKey, + TUserDto Function(Object? json) fromJsonTUserDto, +) => + ExtensibleFullAuditedEntityWithUserDto( + id: fromJsonTPrimaryKey(json['id']), + creator: fromJsonTUserDto(json['creator']), + lastModifier: fromJsonTUserDto(json['lastModifier']), + deleter: fromJsonTUserDto(json['deleter']), + isDeleted: json['isDeleted'] as bool, + deleterId: json['deleterId'] as String?, + deletionTime: json['deletionTime'] == null + ? null + : DateTime.parse(json['deletionTime'] as String), + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map + _$ExtensibleFullAuditedEntityWithUserDtoToJson( + ExtensibleFullAuditedEntityWithUserDto instance, + Object? Function(TPrimaryKey value) toJsonTPrimaryKey, + Object? Function(TUserDto value) toJsonTUserDto, +) => + { + 'extraProperties': instance.extraProperties, + 'id': toJsonTPrimaryKey(instance.id), + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': + instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'isDeleted': instance.isDeleted, + 'deleterId': instance.deleterId, + 'deletionTime': instance.deletionTime?.toIso8601String(), + 'creator': toJsonTUserDto(instance.creator), + 'lastModifier': toJsonTUserDto(instance.lastModifier), + 'deleter': toJsonTUserDto(instance.deleter), + }; + +ListResultDto _$ListResultDtoFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + ListResultDto( + items: (json['items'] as List).map(fromJsonT).toList(), + ); + +Map _$ListResultDtoToJson( + ListResultDto instance, + Object? Function(T value) toJsonT, +) => + { + 'items': instance.items.map(toJsonT).toList(), + }; + +LimitedResultRequestDto _$LimitedResultRequestDtoFromJson( + Map json) => + LimitedResultRequestDto( + maxResultCount: json['maxResultCount'] as int?, + ); + +Map _$LimitedResultRequestDtoToJson( + LimitedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + }; + +ExtensibleLimitedResultRequestDto _$ExtensibleLimitedResultRequestDtoFromJson( + Map json) => + ExtensibleLimitedResultRequestDto( + maxResultCount: json['maxResultCount'] as int?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleLimitedResultRequestDtoToJson( + ExtensibleLimitedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + 'extraProperties': instance.extraProperties, + }; + +ExtensibleListResultDto _$ExtensibleListResultDtoFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + ExtensibleListResultDto( + items: (json['items'] as List).map(fromJsonT).toList(), + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensibleListResultDtoToJson( + ExtensibleListResultDto instance, + Object? Function(T value) toJsonT, +) => + { + 'items': instance.items.map(toJsonT).toList(), + 'extraProperties': instance.extraProperties, + }; + +PagedResultDto _$PagedResultDtoFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + PagedResultDto( + totalCount: json['totalCount'] as int, + items: (json['items'] as List).map(fromJsonT).toList(), + ); + +Map _$PagedResultDtoToJson( + PagedResultDto instance, + Object? Function(T value) toJsonT, +) => + { + 'items': instance.items.map(toJsonT).toList(), + 'totalCount': instance.totalCount, + }; + +ExtensiblePagedResultDto _$ExtensiblePagedResultDtoFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + ExtensiblePagedResultDto( + totalCount: json['totalCount'] as int, + items: (json['items'] as List).map(fromJsonT).toList(), + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensiblePagedResultDtoToJson( + ExtensiblePagedResultDto instance, + Object? Function(T value) toJsonT, +) => + { + 'items': instance.items.map(toJsonT).toList(), + 'totalCount': instance.totalCount, + 'extraProperties': instance.extraProperties, + }; + +SortedResultRequest _$SortedResultRequestFromJson(Map json) => + SortedResultRequest( + sorting: json['sorting'] as String?, + ); + +Map _$SortedResultRequestToJson( + SortedResultRequest instance) => + { + 'sorting': instance.sorting, + }; + +PagedResultRequestDto _$PagedResultRequestDtoFromJson( + Map json) => + PagedResultRequestDto( + skipCount: json['skipCount'] as int?, + maxResultCount: json['maxResultCount'] as int?, + ); + +Map _$PagedResultRequestDtoToJson( + PagedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + 'skipCount': instance.skipCount, + }; + +PagedAndSortedResultRequestDto _$PagedAndSortedResultRequestDtoFromJson( + Map json) => + PagedAndSortedResultRequestDto( + skipCount: json['skipCount'] as int?, + maxResultCount: json['maxResultCount'] as int?, + sorting: json['sorting'] as String?, + ); + +Map _$PagedAndSortedResultRequestDtoToJson( + PagedAndSortedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + 'skipCount': instance.skipCount, + 'sorting': instance.sorting, + }; + +ExtensiblePagedAndSortedResultRequestDto + _$ExtensiblePagedAndSortedResultRequestDtoFromJson( + Map json) => + ExtensiblePagedAndSortedResultRequestDto( + skipCount: json['skipCount'] as int?, + maxResultCount: json['maxResultCount'] as int?, + sorting: json['sorting'] as String?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensiblePagedAndSortedResultRequestDtoToJson( + ExtensiblePagedAndSortedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + 'skipCount': instance.skipCount, + 'sorting': instance.sorting, + 'extraProperties': instance.extraProperties, + }; + +ExtensiblePagedResultRequestDto _$ExtensiblePagedResultRequestDtoFromJson( + Map json) => + ExtensiblePagedResultRequestDto( + skipCount: json['skipCount'] as int?, + maxResultCount: json['maxResultCount'] as int?, + extraProperties: json['extraProperties'] as Map?, + ); + +Map _$ExtensiblePagedResultRequestDtoToJson( + ExtensiblePagedResultRequestDto instance) => + { + 'maxResultCount': instance.maxResultCount, + 'skipCount': instance.skipCount, + 'extraProperties': instance.extraProperties, + }; diff --git a/apps/flutter/core/lib/models/abp.entity.dart b/apps/flutter/core/lib/models/abp.entity.dart new file mode 100644 index 000000000..fe40ac5d5 --- /dev/null +++ b/apps/flutter/core/lib/models/abp.entity.dart @@ -0,0 +1,3 @@ +abstract class IHasConcurrencyStamp { + String? concurrencyStamp; +} \ No newline at end of file diff --git a/apps/flutter/core/lib/models/auth.dart b/apps/flutter/core/lib/models/auth.dart index 43971b78d..f9a422335 100644 --- a/apps/flutter/core/lib/models/auth.dart +++ b/apps/flutter/core/lib/models/auth.dart @@ -221,6 +221,7 @@ class Token { Token({ required this.accessToken, this.expiresIn, + this.expiration, this.tokenType, this.refreshToken, this.scope, @@ -231,6 +232,9 @@ class Token { /// 过期时间 @JsonKey(name: 'expires_in') int? expiresIn; + /// 过期时间 + @JsonKey(name: 'expiration') + DateTime? expiration; /// 令牌类型 @JsonKey(name: 'token_type') String? tokenType; @@ -282,4 +286,34 @@ class UserProfile { factory UserProfile.fromJson(Map json) => _$UserProfileFromJson(json); Map toJson() => _$UserProfileToJson(this); -} \ No newline at end of file +} + +class PortalLoginProvider { + PortalLoginProvider({ + required this.id, + required this.name, + this.logo, + }); + String id; + String name; + String? logo; + + factory PortalLoginProvider.fromJson(Map json) => + PortalLoginProvider( + id: json['Id'] as String, + name: json['Name'] as String, + logo: json['Logo'] as String?, + ); + + Map toJson() => + { + 'Id': id, + 'Name': name, + 'Logo': logo, + }; +} + +class PortalLoginException implements Exception { + PortalLoginException(this.providers); + List providers; +} diff --git a/apps/flutter/core/lib/models/auth.g.dart b/apps/flutter/core/lib/models/auth.g.dart index b406e56bc..0a9c64deb 100644 --- a/apps/flutter/core/lib/models/auth.g.dart +++ b/apps/flutter/core/lib/models/auth.g.dart @@ -128,6 +128,9 @@ Map _$RefreshTokenRequestToJson( Token _$TokenFromJson(Map json) => Token( accessToken: json['access_token'] as String, expiresIn: json['expires_in'] as int?, + expiration: json['expiration'] == null + ? null + : DateTime.tryParse(json['expiration'] as String), tokenType: json['token_type'] as String?, refreshToken: json['refresh_token'] as String?, scope: json['scope'] as String?, @@ -136,6 +139,7 @@ Token _$TokenFromJson(Map json) => Token( Map _$TokenToJson(Token instance) => { 'access_token': instance.accessToken, 'expires_in': instance.expiresIn, + 'expiration': instance.expiration?.toString(), 'token_type': instance.tokenType, 'refresh_token': instance.refreshToken, 'scope': instance.scope, diff --git a/apps/flutter/core/lib/models/common.dart b/apps/flutter/core/lib/models/common.dart index 8942605dc..2573eacc6 100644 --- a/apps/flutter/core/lib/models/common.dart +++ b/apps/flutter/core/lib/models/common.dart @@ -1,3 +1,21 @@ +import 'environment.dart'; + +class Application { + Application({ + required this.environment, + }); + Environment environment; + + factory Application.fromJson(Map json) => Application( + environment: Environment.fromJson(json), + ); + + Map toJson() => + { + 'environment': environment, + }; +} + class Localization { Localization( this.culture, @@ -15,3 +33,12 @@ class LocalizationResource { String resourceName; Map texts; } + +class SignalrMessage { + SignalrMessage( + this.method, + this.data, + ); + String method; + List data; +} diff --git a/apps/flutter/core/lib/models/environment.dart b/apps/flutter/core/lib/models/environment.dart new file mode 100644 index 000000000..0ac766486 --- /dev/null +++ b/apps/flutter/core/lib/models/environment.dart @@ -0,0 +1,342 @@ +import 'package:core/proxy/volo/abp/localization/models.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'environment.g.dart'; + +@JsonSerializable() +class Environment { + Environment({ + required this.application, + required this.remoteServices, + required this.auth, + required this.tenant, + required this.localization, + required this.remoteEnvironment, + this.notifications, + }); + ApplicationConfig application; + RemoteServiceConfig remoteServices; + AuthConfig auth; + TenantConfig tenant; + LocalizationConfig localization; + NotificationConfig? notifications; + RemoteEnvironmentConfig remoteEnvironment; + + factory Environment.empty() { + return Environment( + application: ApplicationConfig(name: ''), + remoteServices: RemoteServiceConfig(services: {}), + auth: AuthConfig(authority: '', clientId: ''), + tenant: TenantConfig(tenantKey: ''), + localization: LocalizationConfig(defaultLanguage: ''), + remoteEnvironment: RemoteEnvironmentConfig(url: 'url'), + ); + } + + factory Environment.fromJson(Map json) => _$EnvironmentFromJson(json); + Map toJson() => _$EnvironmentToJson(this); + + Environment copyWith({ + ApplicationConfig? application, + RemoteServiceConfig? remoteServices, + AuthConfig? auth, + TenantConfig? tenant, + LocalizationConfig? localization, + NotificationConfig? notifications, + RemoteEnvironmentConfig? remoteEnvironment, + }) { + return Environment( + application: application ?? this.application, + remoteServices: remoteServices ?? this.remoteServices, + auth: auth ?? this.auth, + tenant: tenant ?? this.tenant, + localization: localization ?? this.localization, + notifications: notifications ?? this.notifications, + remoteEnvironment: remoteEnvironment ?? this.remoteEnvironment, + ); + } +} + +@JsonEnum() +enum MergeStrategy { + @JsonValue('deepmerge') + deepmerge, + @JsonValue('overwrite') + overwrite; +} + +@JsonSerializable() +class RemoteEnvironmentConfig { + RemoteEnvironmentConfig({ + required this.url, + this.strategy = MergeStrategy.deepmerge, + this.method = 'GET', + this.headers, + }); + String url; + MergeStrategy? strategy; + String? method; + Map? headers; + + factory RemoteEnvironmentConfig.fromJson(Map json) => _$RemoteEnvironmentConfigFromJson(json); + Map toJson() => _$RemoteEnvironmentConfigToJson(this); + + RemoteEnvironmentConfig copyWith({ + String? url, + MergeStrategy? strategy, + String? method, + Map? headers, + }) { + return RemoteEnvironmentConfig( + url: url ?? this.url, + strategy: strategy ?? this.strategy, + method: method ?? this.method, + headers: headers ?? this.headers, + ); + } +} + +@JsonSerializable() +class ApplicationConfig { + ApplicationConfig({ + required this.name, + this.framework = 'flutter', + }); + String name; + String? framework; + + factory ApplicationConfig.fromJson(Map json) => _$ApplicationConfigFromJson(json); + Map toJson() => _$ApplicationConfigToJson(this); + + ApplicationConfig copyWith({ + String? name, + }) { + return ApplicationConfig( + name: name ?? this.name, + ); + } +} + +@JsonSerializable() +class AuthConfig { + AuthConfig({ + required this.authority, + required this.clientId, + this.clientSecret, + }); + String clientId; + String? clientSecret; + String authority; + + factory AuthConfig.fromJson(Map json) => _$AuthConfigFromJson(json); + Map toJson() => _$AuthConfigToJson(this); + + AuthConfig copyWith({ + String? clientId, + String? clientSecret, + String? authority, + }) { + return AuthConfig( + authority: authority ?? this.authority, + clientId: clientId ?? this.clientId, + clientSecret: clientSecret ?? this.clientSecret, + ); + } + + String getAuthority() { + return _mapToAuthority(authority); + } + + String _mapToAuthority(String authority) { + return authority.endsWith('/') ? authority : '$authority/'; + } +} + +@JsonSerializable() +class TenantConfig { + TenantConfig({ + this.tenantKey, + }); + String? tenantKey; + + factory TenantConfig.fromJson(Map json) => _$TenantConfigFromJson(json); + Map toJson() => _$TenantConfigToJson(this); + + TenantConfig copyWith({ + String? tenantKey, + }) { + return TenantConfig( + tenantKey: tenantKey ?? this.tenantKey, + ); + } +} + +@JsonSerializable() +class LocalizationConfig { + LocalizationConfig({ + this.defaultLanguage, + this.useLocalResources = true, + this.supportedLocales = const [], + }); + String? defaultLanguage; + bool? useLocalResources; + List? supportedLocales; + + factory LocalizationConfig.fromJson(Map json) => _$LocalizationConfigFromJson(json); + Map toJson() => _$LocalizationConfigToJson(this); + + LocalizationConfig copyWith({ + String? defaultLanguage, + bool? useLocalResources, + }) { + return LocalizationConfig( + defaultLanguage: defaultLanguage ?? this.defaultLanguage, + useLocalResources: useLocalResources ?? this.useLocalResources, + ); + } +} + +class RemoteServiceConfig { + RemoteServiceConfig({ + required Map services, + }) { + _services = services; + } + late Map _services; + + RemoteService get def => this['default']!; + RemoteService? operator [](String key) => _services[key]; + void operator []=(String key, RemoteService service) => _services[key] = service; + + RemoteServiceConfig copyWith({ + Map? services, + }) { + return RemoteServiceConfig( + services: services ?? _services, + ); + } + + String getApiUrl(String? key) { + return _mapToApiUrl(key)(this); + } + + String Function(RemoteServiceConfig) _mapToApiUrl([String? key]) { + return (RemoteServiceConfig services) { + if (key != null) { + return services[key]?.url ?? services.def.url; + } + return services.def.url; + }; + } +} + +@JsonSerializable() +class RemoteService { + RemoteService({ + required this.url, + this.rootNamespace, + }); + String url; + String? rootNamespace; + + factory RemoteService.fromJson(Map json) => _$RemoteServiceFromJson(json); + Map toJson() => _$RemoteServiceToJson(this); + + RemoteService copyWith({ + String? url, + String? rootNamespace, + }) { + return RemoteService( + url: url ?? this.url, + rootNamespace: rootNamespace ?? this.rootNamespace, + ); + } +} + +@JsonSerializable() +class NotificationConfig { + NotificationConfig({ + this.serverUrl, + this.android, + this.darwin, + this.linux, + }); + String? serverUrl; + AndroidNotification? android; + DarwinNotification? darwin; + LinuxNotification? linux; + + factory NotificationConfig.fromJson(Map json) => _$NotificationConfigFromJson(json); + Map toJson() => _$NotificationConfigToJson(this); + + NotificationConfig copyWith({ + AndroidNotification? android, + DarwinNotification? darwin, + LinuxNotification? linux, + }) { + return NotificationConfig( + android: android ?? this.android, + darwin: darwin ?? this.darwin, + linux: linux ?? this.linux, + ); + } +} + +@JsonSerializable() +class LinuxNotification { + LinuxNotification({ + required this.defaultActionName, + }); + String defaultActionName; + + factory LinuxNotification.fromJson(Map json) => _$LinuxNotificationFromJson(json); + Map toJson() => _$LinuxNotificationToJson(this); + + LinuxNotification copyWith({ + String? defaultActionName, + }) { + return LinuxNotification( + defaultActionName: defaultActionName ?? this.defaultActionName, + ); + } +} + +@JsonSerializable() +class AndroidNotification { + AndroidNotification({ + required this.channelId, + required this.channelName, + this.channelDescription, + }); + String channelId; + String channelName; + String? channelDescription; + + factory AndroidNotification.fromJson(Map json) => _$AndroidNotificationFromJson(json); + Map toJson() => _$AndroidNotificationToJson(this); + + AndroidNotification copyWith({ + String? channelId, + String? channelName, + String? channelDescription, + }) { + return AndroidNotification( + channelId: channelId ?? this.channelId, + channelName: channelName ?? this.channelName, + channelDescription: channelDescription ?? this.channelDescription, + ); + } +} + +@JsonSerializable() +class DarwinNotification { + DarwinNotification(); + + factory DarwinNotification.fromJson(Map json) => _$DarwinNotificationFromJson(json); + Map toJson() => _$DarwinNotificationToJson(this); + + DarwinNotification copyWith() { + return DarwinNotification( + ); + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/models/environment.g.dart b/apps/flutter/core/lib/models/environment.g.dart new file mode 100644 index 000000000..07efcf04e --- /dev/null +++ b/apps/flutter/core/lib/models/environment.g.dart @@ -0,0 +1,178 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'environment.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Environment _$EnvironmentFromJson(Map json) => Environment( + application: ApplicationConfig.fromJson( + json['application'] as Map), + remoteServices: RemoteServiceConfig( + services: (json['remoteServices'] as Map) + .map((key, value) => MapEntry(key, RemoteService.fromJson(value as Map)))), + auth: AuthConfig.fromJson(json['auth'] as Map), + tenant: TenantConfig.fromJson(json['tenant'] as Map), + localization: LocalizationConfig.fromJson( + json['localization'] as Map), + remoteEnvironment: RemoteEnvironmentConfig.fromJson( + json['remoteEnvironment'] as Map), + notifications: json['notifications'] == null + ? null + : NotificationConfig.fromJson( + json['notifications'] as Map), + ); + +Map _$EnvironmentToJson(Environment instance) => + { + 'application': instance.application, + 'remoteServices': instance.remoteServices, + 'auth': instance.auth, + 'tenant': instance.tenant, + 'localization': instance.localization, + 'notifications': instance.notifications, + 'remoteEnvironment': instance.remoteEnvironment, + }; + +RemoteEnvironmentConfig _$RemoteEnvironmentConfigFromJson( + Map json) => + RemoteEnvironmentConfig( + url: json['url'] as String, + strategy: $enumDecodeNullable(_$MergeStrategyEnumMap, json['strategy']) ?? + MergeStrategy.deepmerge, + method: json['method'] as String? ?? 'GET', + headers: (json['headers'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + ); + +Map _$RemoteEnvironmentConfigToJson( + RemoteEnvironmentConfig instance) => + { + 'url': instance.url, + 'strategy': _$MergeStrategyEnumMap[instance.strategy], + 'method': instance.method, + 'headers': instance.headers, + }; + +const _$MergeStrategyEnumMap = { + MergeStrategy.deepmerge: 'deepmerge', + MergeStrategy.overwrite: 'overwrite', +}; + +ApplicationConfig _$ApplicationConfigFromJson(Map json) => + ApplicationConfig( + name: json['name'] as String, + framework: json['framework'] as String?, + ); + +Map _$ApplicationConfigToJson(ApplicationConfig instance) => + { + 'name': instance.name, + 'framework': instance.framework, + }; + +AuthConfig _$AuthConfigFromJson(Map json) => AuthConfig( + authority: json['authority'] as String, + clientId: json['clientId'] as String, + clientSecret: json['clientSecret'] as String?, + ); + +Map _$AuthConfigToJson(AuthConfig instance) => + { + 'clientId': instance.clientId, + 'clientSecret': instance.clientSecret, + 'authority': instance.authority, + }; + +TenantConfig _$TenantConfigFromJson(Map json) => TenantConfig( + tenantKey: json['tenantKey'] as String?, + ); + +Map _$TenantConfigToJson(TenantConfig instance) => + { + 'tenantKey': instance.tenantKey, + }; + +LocalizationConfig _$LocalizationConfigFromJson(Map json) => + LocalizationConfig( + defaultLanguage: json['defaultLanguage'] as String?, + useLocalResources: json['useLocalResources'] as bool?, + supportedLocales: json['supportedLocales'] != null + ? (json['supportedLocales'] as List).map((e) => LanguageInfo.fromJson(e)).toList() + : null, + ); + +Map _$LocalizationConfigToJson(LocalizationConfig instance) => + { + 'defaultLanguage': instance.defaultLanguage, + 'useLocalResources': instance.useLocalResources, + 'supportedLocales': instance.supportedLocales, + }; + +RemoteService _$RemoteServiceFromJson(Map json) => + RemoteService( + url: json['url'] as String, + rootNamespace: json['rootNamespace'] as String?, + ); + +Map _$RemoteServiceToJson(RemoteService instance) => + { + 'url': instance.url, + 'rootNamespace': instance.rootNamespace, + }; + +NotificationConfig _$NotificationConfigFromJson(Map json) => + NotificationConfig( + serverUrl: json['serverUrl'] as String?, + android: json['android'] == null + ? null + : AndroidNotification.fromJson( + json['android'] as Map), + darwin: json['darwin'] == null + ? null + : DarwinNotification.fromJson(json['darwin'] as Map), + linux: json['linux'] == null + ? null + : LinuxNotification.fromJson(json['linux'] as Map), + ); + +Map _$NotificationConfigToJson(NotificationConfig instance) => + { + 'serverUrl': instance.serverUrl, + 'android': instance.android, + 'darwin': instance.darwin, + 'linux': instance.linux, + }; + +LinuxNotification _$LinuxNotificationFromJson(Map json) => + LinuxNotification( + defaultActionName: json['defaultActionName'] as String, + ); + +Map _$LinuxNotificationToJson(LinuxNotification instance) => + { + 'defaultActionName': instance.defaultActionName, + }; + +AndroidNotification _$AndroidNotificationFromJson(Map json) => + AndroidNotification( + channelId: json['channelId'] as String, + channelName: json['channelName'] as String, + channelDescription: json['channelDescription'] as String?, + ); + +Map _$AndroidNotificationToJson( + AndroidNotification instance) => + { + 'channelId': instance.channelId, + 'channelName': instance.channelName, + 'channelDescription': instance.channelDescription, + }; + +DarwinNotification _$DarwinNotificationFromJson(Map json) => + DarwinNotification(); + +Map _$DarwinNotificationToJson(DarwinNotification instance) => + {}; diff --git a/apps/flutter/core/lib/models/index.dart b/apps/flutter/core/lib/models/index.dart index 7048bdbc3..786806fe4 100644 --- a/apps/flutter/core/lib/models/index.dart +++ b/apps/flutter/core/lib/models/index.dart @@ -1,7 +1,9 @@ export 'abp.dto.dart'; +export 'abp.entity.dart'; export 'abp.error.dart'; export 'auth.dart'; export 'common.dart'; +export 'environment.dart'; export 'oauth.dart'; export 'session.dart'; export 'theme.dart'; diff --git a/apps/flutter/core/lib/models/request.dart b/apps/flutter/core/lib/models/request.dart new file mode 100644 index 000000000..ebae2f966 --- /dev/null +++ b/apps/flutter/core/lib/models/request.dart @@ -0,0 +1,20 @@ +import 'package:dio/dio.dart'; + +class RequestOptions { + RequestOptions({ + CancelToken? cancelToken, + this.sendTimeout, + this.receiveTimeout, + this.headers, + }) { + this.cancelToken = cancelToken ?? CancelToken(); + } + late CancelToken? cancelToken; + late Duration? sendTimeout; + late Duration? receiveTimeout; + late Map? headers; + + void cancel() { + cancelToken?.cancel(); + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/models/session.dart b/apps/flutter/core/lib/models/session.dart index d8ab12c03..70ac00557 100644 --- a/apps/flutter/core/lib/models/session.dart +++ b/apps/flutter/core/lib/models/session.dart @@ -5,7 +5,6 @@ import 'package:json_annotation/json_annotation.dart'; part 'session.g.dart'; -/// 企业平台认证请求承载体 @JsonSerializable() class Session extends CloneObject { Session({ diff --git a/apps/flutter/core/lib/modularity/module.dart b/apps/flutter/core/lib/modularity/module.dart index 4f581b334..11c0df393 100644 --- a/apps/flutter/core/lib/modularity/module.dart +++ b/apps/flutter/core/lib/modularity/module.dart @@ -1,11 +1,13 @@ import 'package:get/get.dart'; +import '../dependency/index.dart'; import 'module.key.dart'; abstract class Module { - static final Map _initModuleMap = {}; - List get dependencies => const []; + late bool isInitlized= false; + Injector get injector => Injector.instance; + List get dependencies => const []; List get routes => const []; Future configureServicesAsync() { @@ -16,79 +18,73 @@ abstract class Module { } + T get({String? tag}) => injector.get(tag: tag); + T inject( T dependency, { String? tag, bool permanent = false, - InstanceBuilderCallback? builder, - }) => Get.put(dependency, tag: tag, permanent: permanent, builder: builder); + InjectorBuilderFactory? builder, + }) => injector.inject(dependency, tag: tag, permanent: permanent, builder: builder); void create( - InstanceBuilderCallback builder, + InjectorBuilderFactory builder, { String? tag, bool permanent = true, } - ) => Get.create(builder, tag: tag, permanent: permanent); + ) => injector.create(builder, tag: tag, permanent: permanent); void lazyInject( - InstanceBuilderCallback builder, + InjectorBuilderFactory builder, { String? tag, bool fenix = false, - }) => Get.lazyPut(builder, tag: tag, fenix: fenix); + }) => injector.lazyInject(builder, tag: tag, fenix: fenix); Future injectAsync( - AsyncInstanceBuilderCallback builder, + AsyncInjectorBuilderFactory builder, { String? tag, bool permanent = false, - }) => Get.putAsync(builder, tag: tag, permanent: permanent); + }) => injector.injectAsync(builder, tag: tag, permanent: permanent); - bool isInjected({String? tag}) => Get.isRegistered(tag: tag); + bool isInjected({String? tag}) => injector.isInjected(tag: tag); Future>> initAsync() async { - final routeMap = >{}; + var routeMap = >{}; + if (isInitlized) return routeMap; for (var dependency in dependencies) { - if (_initModuleMap.containsKey(dependency)) { - continue; - } - await dependency.configureServicesAsync(); var childrenRoute = await dependency.initAsync(); routeMap.addAll(childrenRoute); - _initModuleMap[dependency] = true; } await configureServicesAsync(); - routeMap.assign(ModuleKey(toString()), routes); - _initModuleMap[this] = true; + routeMap.putIfAbsent(ModuleKey(toString()), () => routes); + isInitlized = true; return routeMap; } Map> init() { - final routeMap = >{}; + var routeMap = >{}; + if (isInitlized) return routeMap; for (var dependency in dependencies) { - if (_initModuleMap.containsKey(dependency)) { - continue; - } - dependency.configureServices(); var childrenRoute = dependency.init(); routeMap.addAll(childrenRoute); - _initModuleMap[dependency] = true; } configureServices(); - routeMap.assign(ModuleKey(toString()), routes); - _initModuleMap[this] = true; + routeMap.putIfAbsent(ModuleKey(toString()), () => routes); + isInitlized = true; return routeMap; } List getRoutes() { List findRoutes = []; - findRoutes.addAll(routes); for (var dependency in dependencies) { - findRoutes.addAll(dependency.routes); + findRoutes.addAll(dependency.getRoutes()); + } - + findRoutes.addAll(routes); return findRoutes; } } \ No newline at end of file diff --git a/apps/flutter/core/lib/proxy/lingyun/abp/asp-net-core/mvc/localization/language.service.dart b/apps/flutter/core/lib/proxy/lingyun/abp/asp-net-core/mvc/localization/language.service.dart index 90e50e2c1..cb60b637f 100644 --- a/apps/flutter/core/lib/proxy/lingyun/abp/asp-net-core/mvc/localization/language.service.dart +++ b/apps/flutter/core/lib/proxy/lingyun/abp/asp-net-core/mvc/localization/language.service.dart @@ -1,17 +1,22 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/models/abp.dto.dart'; import 'package:core/proxy/volo/abp/localization/models.dart'; import 'package:core/services/rest.service.dart'; -import 'package:get/get.dart'; class LanguageService { - RestService get _restService => Get.find(); + LanguageService(Injector injector): + _restService = injector.get(); + final RestService _restService; Future> getList() { - return _restService.get('/api/abp/localization/languages') - .then((res) { - return ListResultDto( - items: (res.data['items'] as List).map((e) => LanguageInfo.fromJson(e)).toList(), - ); - }); + return _restService.request>( + method: HttpMethod.GET, + url: '/api/abp/localization/languages', + transformer: (res) { + return ListResultDto( + items: (res.data['items'] as List).map((e) => LanguageInfo.fromJson(e)).toList(), + ); + } + ); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.dart b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.dart index 6b41f3fe5..3d94e66c5 100644 --- a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.dart +++ b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/api-exploring/abp-api-definition.service.dart @@ -1,15 +1,21 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/proxy/volo/abp/http/modeling/index.dart'; import 'package:core/services/rest.service.dart'; -import 'package:get/get.dart'; class AbpApiDefinitionService { - final RestService _restService = Get.find(); + AbpApiDefinitionService(Injector injector): + _restService = injector.get(); + final RestService _restService; Future getByModel(ApplicationApiDescriptionModelRequestDto model) { - return _restService.get('/api/abp/api-definition', + return _restService.request( + method: HttpMethod.GET, + url: '/api/abp/api-definition', queryParameters: { 'includeTypes': model.includeTypes - }).then((res) => ApplicationApiDescriptionModel.fromJson(res.data)); + }, + transformer: (res) => ApplicationApiDescriptionModel.fromJson(res.data), + ); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.dart b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.dart index 9336eeaa3..ade002886 100644 --- a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.dart +++ b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service.dart @@ -1,16 +1,20 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/proxy/volo/abp/asp-net-core/mvc/application-configurations/index.dart'; import 'package:core/services/rest.service.dart'; -import 'package:get/get.dart'; class AbpApplicationConfigurationService { - RestService get _restService => Get.find(); + AbpApplicationConfigurationService(Injector injector): + _restService = injector.get(); + final RestService _restService; Future get(ApplicationConfigurationRequestOptions options) { - return _restService.get('/api/abp/application-configuration', + return _restService.request( + method: HttpMethod.GET, + url: '/api/abp/application-configuration', queryParameters: { 'includeLocalizationResources': options.includeLocalizationResources - }).then((res) { - return ApplicationConfigurationDto.fromJson(res.data); - }); + }, + transformer: (res) => ApplicationConfigurationDto.fromJson(res.data), + ); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.dart b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.dart index ecccaf64b..2ff53c74e 100644 --- a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.dart +++ b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service.dart @@ -1,16 +1,22 @@ -import 'package:get/get.dart'; +import 'package:core/dependency/injector.dart'; import 'models.dart'; import 'package:core/services/rest.service.dart'; class AbpApplicationLocalizationService { - RestService get _restService => Get.find(); + AbpApplicationLocalizationService(Injector injector): + _restService = injector.get(); + final RestService _restService; Future get(ApplicationLocalizationRequestDto input) { - return _restService.get('/api/abp/application-localization', + return _restService.request( + method: HttpMethod.GET, + url: '/api/abp/application-localization', queryParameters: { 'cultureName': input.cultureName, 'onlyDynamics': input.onlyDynamics - }).then((res) => ApplicationLocalizationDto.fromJson(res.data)); + }, + transformer: (res) => ApplicationLocalizationDto.fromJson(res.data) + ); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/multi-tenancy/abp-tenant.service.dart b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/multi-tenancy/abp-tenant.service.dart index 6f69cbb5b..fa554eabf 100644 --- a/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/multi-tenancy/abp-tenant.service.dart +++ b/apps/flutter/core/lib/proxy/volo/abp/asp-net-core/mvc/multi-tenancy/abp-tenant.service.dart @@ -1,18 +1,26 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/services/rest.service.dart'; -import 'package:get/get.dart'; import 'models.dart'; class AbpTenantService { - RestService get _restService => Get.find(); + AbpTenantService(Injector injector): + _restService = injector.get(); + final RestService _restService; Future findTenantById(String id) { - return _restService.get('/api/abp/multi-tenancy/tenants/by-id/$id') - .then((res) => FindTenantResultDto.fromJson(res.data)); + return _restService.request( + method: HttpMethod.GET, + url: '/api/abp/multi-tenancy/tenants/by-id/$id', + transformer: (res) => FindTenantResultDto.fromJson(res.data), + ); } Future findTenantByName(String name) { - return _restService.get('/api/abp/multi-tenancy/tenants/by-name/$name') - .then((res) => FindTenantResultDto.fromJson(res.data)); + return _restService.request( + method: HttpMethod.GET, + url: '/api/abp/multi-tenancy/tenants/by-name/$name', + transformer: (res) => FindTenantResultDto.fromJson(res.data), + ); } } \ No newline at end of file diff --git a/apps/flutter/core/lib/services/application.initial.dart b/apps/flutter/core/lib/services/application.initial.dart new file mode 100644 index 000000000..2695d525a --- /dev/null +++ b/apps/flutter/core/lib/services/application.initial.dart @@ -0,0 +1,5 @@ +import 'package:core/models/index.dart'; + +abstract class ApplicationInitialService { + Future initialApp(); +} \ No newline at end of file diff --git a/apps/flutter/core/lib/services/auth.service.dart b/apps/flutter/core/lib/services/auth.service.dart index d42c84118..58c2bd4e3 100644 --- a/apps/flutter/core/lib/services/auth.service.dart +++ b/apps/flutter/core/lib/services/auth.service.dart @@ -1,14 +1,14 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/models/auth.dart'; import 'package:core/models/oauth.dart'; -import 'package:get/get.dart'; import '../utils/logging.dart'; import 'service.base.dart'; abstract class AuthService extends ServiceBase { - - static AuthService get to => Get.find(); + AuthService(super._injector); + static AuthService get to => Injector.instance.get(); Future password(LoginParams params) { logger.debug('not implemented'); @@ -30,8 +30,8 @@ abstract class AuthService extends ServiceBase { return Future.error('not implemented'); } - Future getProfile() { - logger.debug('not implemented'); - return Future.error('not implemented'); - } + // Future getProfile() { + // logger.debug('not implemented'); + // return Future.error('not implemented'); + // } } \ No newline at end of file diff --git a/apps/flutter/core/lib/services/config.state.service.dart b/apps/flutter/core/lib/services/config.state.service.dart index 3c9dbd019..96bcbce1e 100644 --- a/apps/flutter/core/lib/services/config.state.service.dart +++ b/apps/flutter/core/lib/services/config.state.service.dart @@ -1,15 +1,21 @@ import 'dart:async'; +import 'package:core/proxy/volo/abp/localization/models.dart'; import 'package:core/utils/string.extensions.dart'; import 'package:rxdart/rxdart.dart'; +import 'environment.service.dart'; import 'service.base.dart'; import 'package:core/utils/internal.store.dart'; import 'package:core/proxy/volo/abp/asp-net-core/mvc/application-configurations/index.dart'; class ConfigStateService extends ServiceBase { - AbpApplicationConfigurationService get abpConfigService => find(); - AbpApplicationLocalizationService get abpApplicationLocalizationService => find(); + ConfigStateService(super._injector); + + EnvironmentService get _environmentService => resolve(); + AbpApplicationConfigurationService get _abpConfigService => resolve(); + AbpApplicationLocalizationService get _abpApplicationLocalizationService => resolve(); + final bool? includeLocalizationResources = false; final InternalStore _store = InternalStore(state: ApplicationConfigurationDto()); @@ -31,13 +37,16 @@ class ConfigStateService extends ServiceBase { _updateSubject .switchMap((_) => Stream.fromFuture(getAbpConfig())) .switchMap((appState) => Stream.fromFuture(getLocalizationAndCombineWithAppState(appState))) - .listen((appState) => _store.set(appState)); + .listen(_store.set); } Future getLocalizationAndCombineWithAppState(ApplicationConfigurationDto appState) { if (appState.localization?.currentCulture?.cultureName?.isNullOrWhiteSpace() == true) { throw Exception('culture name should defined'); } + var environment = _environmentService.getEnvironment(); + if (environment.localization.useLocalResources == true) return Future.value(appState); + return getlocalizationResource(appState.localization!.currentCulture!.cultureName!) .then((localization) { var abpConfig = appState.cloneWith((state) { @@ -53,13 +62,13 @@ class ConfigStateService extends ServiceBase { } Future getlocalizationResource(String cultureName) { - return abpApplicationLocalizationService.get(ApplicationLocalizationRequestDto( + return _abpApplicationLocalizationService.get(ApplicationLocalizationRequestDto( cultureName: cultureName, onlyDynamics: false)); } Future getAbpConfig() { - return abpConfigService.get(ApplicationConfigurationRequestOptions( + return _abpConfigService.get(ApplicationConfigurationRequestOptions( includeLocalizationResources: includeLocalizationResources )); } @@ -128,4 +137,12 @@ class ConfigStateService extends ServiceBase { bool getGlobalFeatureIsEnabled(String key) { return _isGlobalFeatureEnabled(key, _store.state.globalFeatures!); } + + List? getSupportedLocales() { + var environment = _environmentService.getEnvironment(); + if (environment.localization.useLocalResources == true) { + return _environmentService.getSupportedLocales(); + } + return _store.state.localization?.languages; + } } \ No newline at end of file diff --git a/apps/flutter/core/lib/services/environment.service.dart b/apps/flutter/core/lib/services/environment.service.dart new file mode 100644 index 000000000..cc037ed62 --- /dev/null +++ b/apps/flutter/core/lib/services/environment.service.dart @@ -0,0 +1,49 @@ +import 'package:core/dependency/injector.dart'; +import 'package:core/models/environment.dart'; +import 'package:core/proxy/volo/abp/localization/models.dart'; +import 'package:core/utils/index.dart'; + +import 'service.base.dart'; + +class EnvironmentService extends ServiceBase { + EnvironmentService(super._injector); + + static EnvironmentService get to => Injector.instance.get(); + + final InternalStore _store = InternalStore(state: Environment.empty()); + + Stream get createOnUpdateStream { + return _store.sliceUpdate((state) => state); + } + + setState(Environment environment) { + _store.set(environment); + } + + Stream getEnvironment$() { + return _store.sliceState((state) => state); + } + + Environment getEnvironment() { + return _store.state; + } + + Stream getApiUrl$(String? key) { + return _store.sliceState((state) => state.remoteServices).map((services) => services.getApiUrl(key)); + } + String getApiUrl(String? key) { + return _store.state.remoteServices.getApiUrl(key); + } + + Stream getAuthority$() { + return _store.sliceState((state) => state.auth).map((auth) => auth.getAuthority()); + } + + String getAuthority() { + return _store.state.auth.getAuthority(); + } + + List getSupportedLocales() { + return _store.state.localization.supportedLocales ?? []; + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/services/error.reporter.service.dart b/apps/flutter/core/lib/services/error.reporter.service.dart new file mode 100644 index 000000000..689f89465 --- /dev/null +++ b/apps/flutter/core/lib/services/error.reporter.service.dart @@ -0,0 +1,14 @@ +import 'package:rxdart/rxdart.dart'; + +class ErrorReporterService { + final Subject _reporter$ = BehaviorSubject(); + final BehaviorSubject> _errors$ = BehaviorSubject>.seeded([]); + + Stream getReporter$() => _reporter$; + Stream> getErrors$() => _errors$; + + void reportError(Exception exception){ + _reporter$.add(exception); + _errors$.add([..._errors$.value, exception]); + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/services/index.dart b/apps/flutter/core/lib/services/index.dart index 6fa2e219f..00962959c 100644 --- a/apps/flutter/core/lib/services/index.dart +++ b/apps/flutter/core/lib/services/index.dart @@ -1,5 +1,8 @@ +export 'application.initial.dart'; export 'auth.service.dart'; export 'config.state.service.dart'; +export 'environment.service.dart'; +export 'error.reporter.service.dart'; export 'localization.service.dart'; export 'notification.send.service.dart'; export 'rest.service.dart'; @@ -7,4 +10,4 @@ export 'storage.service.dart'; export 'session.service.dart'; export 'subscription.service.dart'; export 'theme.service.dart'; -export 'signalr.service.dart'; \ No newline at end of file +export 'translation.service.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/services/localization.service.dart b/apps/flutter/core/lib/services/localization.service.dart index 4ac66f66c..77e43bc19 100644 --- a/apps/flutter/core/lib/services/localization.service.dart +++ b/apps/flutter/core/lib/services/localization.service.dart @@ -1,3 +1,4 @@ +import 'package:core/dependency/injector.dart'; import 'package:core/models/common.dart'; import 'package:core/services/index.dart'; import 'package:core/utils/localization.utils.dart'; @@ -10,14 +11,16 @@ import 'package:rxdart_ext/rxdart_ext.dart'; import '../proxy/volo/abp/asp-net-core/mvc/index.dart'; import 'service.base.dart'; -class LocalizationService extends ServiceBase { - StorageService get storageService => find(); - SessionService get sessionService => find(); - ConfigStateService get configStateService => find(); +class LocalizationService extends ServiceBase implements TranslationService { + LocalizationService(super._injector); + + SessionService get _sessionService => resolve(); + ConfigStateService get _configStateService => resolve(); + EnvironmentService get _environmentService => resolve(); - String? get currentLang => sessionService.currentLanguage; + String? get currentLang => _sessionService.currentLanguage; - static LocalizationService get to => Get.find(); + static LocalizationService get to => Injector.instance.get(); final Subject _localization$ = BehaviorSubject(); final BehaviorSubject>> _localizations$ = BehaviorSubject>>.seeded({}); @@ -32,8 +35,8 @@ class LocalizationService extends ServiceBase { void _initLocalizationValues() { // var legacyResources$ = configStateService.sliceConfig((config) => config.localization?.values); // var remoteLocalizations$ = configStateService.sliceConfig((config) => config.localization?.resources); - var currentLanguage$ = sessionService.getLanguage$(); - var localizations$ = configStateService.getLocalization$(); + var currentLanguage$ = _sessionService.getLanguage$(); + var localizations$ = _configStateService.getLocalization$(); // 本地化 Rx.combineLatest2(currentLanguage$, localizations$, (currentLang, localizations) { @@ -55,6 +58,10 @@ class LocalizationService extends ServiceBase { .listen((localization) => _localization$.add(localization)); _localization$ + .where((localization) { + var environment = _environmentService.getEnvironment(); + return environment.localization.useLocalResources == false; + }) .listen((localization) async { Map> localizations = {}; Map cultureMap = {}; @@ -67,33 +74,31 @@ class LocalizationService extends ServiceBase { Get.clearTranslations(); Get.addTranslations(localizations); - await Get.updateLocale(Locale.fromSubtags(languageCode: localization.culture)); - _localizations$.add(localizations); }); } void _listenToSetLanguage() { - var lanuage$ = sessionService.onLanguageChange$(); - var localization$ = configStateService.getLocalization$(); + var lanuage$ = _sessionService.onLanguageChange$(); + var localization$ = _configStateService.getLocalization$(); Rx.combineLatest2(lanuage$, localization$, (lang, localization) { if (localization?.currentCulture?.cultureName == null) return null; if (lang == localization?.currentCulture?.cultureName) return null; return lang; }).whereNotNull() - .listen((_) => configStateService.refreshAppState()); + .listen((_) => _configStateService.refreshAppState()); } Stream localize(String resourceName, String key, {String? defaultValue}) { - return configStateService.getLocalization$() + return _configStateService.getLocalization$() .map((localization) => LocalizationUtils.createLocalizer(localization)) .map((localize) => localize(resourceName, key, defaultValue ?? key)); } String localizeSync(String resourceName, String key, {String? defaultValue}) { - var localization = configStateService.getLocalization(); + var localization = _configStateService.getLocalization(); return LocalizationUtils.createLocalizer(localization)(resourceName, key, defaultValue ?? key); } @@ -102,7 +107,7 @@ class LocalizationService extends ServiceBase { List keys, String defaultValue, ) { - return configStateService.getLocalization$() + return _configStateService.getLocalization$() .map((localization) => LocalizationUtils.createLocalizerWithFallback(localization!)) .map((localizeWithFallback) => localizeWithFallback(resourceNames, keys, defaultValue), ); @@ -113,10 +118,11 @@ class LocalizationService extends ServiceBase { List keys, String defaultValue, ) { - var localization = configStateService.getLocalization(); + var localization = _configStateService.getLocalization(); return LocalizationUtils.createLocalizerWithFallback(localization!)(resourceNames, keys, defaultValue); } + @override Map> getResources() { return _localizations$.value; } diff --git a/apps/flutter/core/lib/services/notification.send.service.dart b/apps/flutter/core/lib/services/notification.send.service.dart index 7fc0db708..85a9357f2 100644 --- a/apps/flutter/core/lib/services/notification.send.service.dart +++ b/apps/flutter/core/lib/services/notification.send.service.dart @@ -1,5 +1,6 @@ import 'package:core/services/service.base.dart'; abstract class NotificationSendService extends ServiceBase { + NotificationSendService(super._injector); Future send(String title, [String? body, String? payload]); } \ No newline at end of file diff --git a/apps/flutter/core/lib/services/rest.service.dart b/apps/flutter/core/lib/services/rest.service.dart index fe9387558..f33543e47 100644 --- a/apps/flutter/core/lib/services/rest.service.dart +++ b/apps/flutter/core/lib/services/rest.service.dart @@ -1,287 +1,78 @@ -import 'package:dio/dio.dart'; -import 'package:get/get.dart' hide Response; +import 'dart:async'; -class RestService implements Dio { - RestService({ - required this.dio, - }); - late Dio dio; +import 'package:core/dependency/injector.dart'; +import 'package:core/models/request.dart'; +import 'package:dio/dio.dart' hide RequestOptions; - static RestService get to => Get.find(); - - @override - HttpClientAdapter get httpClientAdapter => dio.httpClientAdapter; +import 'environment.service.dart'; - @override - set httpClientAdapter(adapter) => dio.httpClientAdapter = adapter; - - @override - BaseOptions get options => dio.options; - - @override - set options(opt) => dio.options = opt; +class HttpMethod { + // ignore: constant_identifier_names + static const String GET = "GET"; + // ignore: constant_identifier_names + static const String POST = "POST"; + // ignore: constant_identifier_names + static const String PATCH = "PATCH"; + // ignore: constant_identifier_names + static const String PUT = "PUT"; + // ignore: constant_identifier_names + static const String DELETE = "DELETE"; + // ignore: constant_identifier_names + static const String OPTIONS = "OPTIONS"; + // ignore: constant_identifier_names + static const String HEAD = "HEAD"; +} - @override - Transformer get transformer => dio.transformer; +class RestService { + RestService( + this.dio, + this._environmentService); + late Dio dio; + late final EnvironmentService _environmentService; - @override - set transformer(trans) => dio.transformer = trans; + static RestService get to => injector.get(); - @override - Interceptors get interceptors => dio.interceptors; - - @override - void close({bool force = false}) => dio.close(force: force); - - @override - Future> fetch(RequestOptions requestOptions) => dio.fetch(requestOptions); - - @override - Future> get( - String path, + Future request( { + required String url, + required String method, + T Function(Response response)? transformer, + RequestOptions? requestOptions, + String? apiName, Object? data, Map? queryParameters, - Options? options, CancelToken? cancelToken, + Options? options, + ProgressCallback? onSendProgress, ProgressCallback? onReceiveProgress, - }) => dio.get(path, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken, - onReceiveProgress: onReceiveProgress); - - @override - Future> getUri( - Uri uri, { - Object? data, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onReceiveProgress, - }) => dio.getUri(uri, - data: data, - options: options, - cancelToken: cancelToken, - onReceiveProgress: onReceiveProgress); - - @override - Future> post( - String path, { - Object? data, - Map? queryParameters, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.post(path, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); + }) { + options ??= options?.copyWith( + method: method, + sendTimeout: requestOptions?.sendTimeout, + receiveTimeout: requestOptions?.receiveTimeout, + headers: requestOptions?.headers, + ) + ?? Options( + method: method, + sendTimeout: requestOptions?.sendTimeout, + receiveTimeout: requestOptions?.receiveTimeout, + headers: requestOptions?.headers, + ); - @override - Future> postUri( - Uri uri, { - Object? data, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.postUri(uri, - data: data, - options: options, - cancelToken: cancelToken, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); + var apiUrl = _environmentService.getApiUrl(apiName); + url = removeDuplicateSlashes(apiUrl + url); - @override - Future> put( - String path, { - Object? data, - Map? queryParameters, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.put(path, + return dio.request(url, data: data, queryParameters: queryParameters, + cancelToken: cancelToken ?? requestOptions?.cancelToken, options: options, - cancelToken: cancelToken, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); - - @override - Future> putUri( - Uri uri, { - Object? data, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.putUri(uri, - data: data, - options: options, - cancelToken: cancelToken, onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); - - @override - Future> head( - String path, { - Object? data, - Map? queryParameters, - Options? options, - CancelToken? cancelToken, - }) => dio.head(path, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken); + onReceiveProgress: onReceiveProgress) + .then((response) => transformer != null ? transformer(response) : null as T); + } - @override - Future> headUri( - Uri uri, { - Object? data, - Options? options, - CancelToken? cancelToken, - }) => dio.headUri(uri, - data: data, - options: options, - cancelToken: cancelToken); - - @override - Future> delete( - String path, - { - Object? data, - Map? queryParameters, - Options? options, - CancelToken? cancelToken, - }) => dio.delete(path, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken); - - @override - Future> deleteUri( - Uri uri, - { - Object? data, - Options? options, - CancelToken? cancelToken, - }) => dio.deleteUri(uri, - data: data, - options: options, - cancelToken: cancelToken); - - @override - Future download( - String urlPath, savePath, - { - ProgressCallback? onReceiveProgress, - Map? queryParameters, - CancelToken? cancelToken, - bool deleteOnError = true, - String lengthHeader = Headers.contentLengthHeader, - Object? data, - Options? options, - }) => dio.download(urlPath, savePath, - onReceiveProgress: onReceiveProgress, - queryParameters: queryParameters, - cancelToken: cancelToken, - deleteOnError: deleteOnError, - lengthHeader: lengthHeader, - data: data, - options: options); - - @override - Future downloadUri( - Uri uri, savePath, - { - ProgressCallback? onReceiveProgress, - CancelToken? cancelToken, - bool deleteOnError = true, - String lengthHeader = Headers.contentLengthHeader, - Object? data, - Options? options, - }) => dio.downloadUri(uri, savePath, - onReceiveProgress: onReceiveProgress, - cancelToken: cancelToken, - deleteOnError: deleteOnError, - lengthHeader: lengthHeader, - data: data, - options: options); - - @override - Future> patch( - String path, - { - Object? data, - Map? queryParameters, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.patch(path, - data: data, - queryParameters: queryParameters, - options: options, - cancelToken: cancelToken, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); - - @override - Future> patchUri( - Uri uri, - { - Object? data, - Options? options, - CancelToken? cancelToken, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.patchUri(uri, - data: data, - options: options, - cancelToken: cancelToken, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); - - @override - Future> request( - String path, - { - Object? data, - Map? queryParameters, - CancelToken? cancelToken, - Options? options, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.request(path, - data: data, - queryParameters: queryParameters, - cancelToken: cancelToken, - options: options, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); - - @override - Future> requestUri( - Uri uri, - { - Object? data, - CancelToken? cancelToken, - Options? options, - ProgressCallback? onSendProgress, - ProgressCallback? onReceiveProgress, - }) => dio.requestUri(uri, - data: data, - cancelToken: cancelToken, - options: options, - onSendProgress: onSendProgress, - onReceiveProgress: onReceiveProgress); + String removeDuplicateSlashes(String url) { + return url.replaceAll(RegExp('/([^:]/)/+/g'), '\$1'); + } } diff --git a/apps/flutter/core/lib/services/service.base.dart b/apps/flutter/core/lib/services/service.base.dart index c270ed807..6bf54f59e 100644 --- a/apps/flutter/core/lib/services/service.base.dart +++ b/apps/flutter/core/lib/services/service.base.dart @@ -1,5 +1,8 @@ +import 'package:core/dependency/index.dart'; import 'package:get/get.dart'; abstract class ServiceBase extends GetxService { - T find({ String? tag}) => Get.find(tag: tag); + ServiceBase(this._injector); + final Injector _injector; + T resolve({ String? tag}) => _injector.get(tag: tag); } \ No newline at end of file diff --git a/apps/flutter/core/lib/services/session.service.dart b/apps/flutter/core/lib/services/session.service.dart index 78d939b67..a4335e08d 100644 --- a/apps/flutter/core/lib/services/session.service.dart +++ b/apps/flutter/core/lib/services/session.service.dart @@ -8,20 +8,23 @@ import 'package:core/utils/string.extensions.dart'; import 'package:get/get.dart'; import 'package:rxdart/rxdart.dart'; -import 'auth.service.dart'; +import '../dependency/injector.dart'; +import 'environment.service.dart'; import 'storage.service.dart'; import 'config.state.service.dart'; import 'service.base.dart'; class SessionService extends ServiceBase { + SessionService(super._injector); + static const String sessionKey = '_abp_session_'; final InternalStore _store = InternalStore(state: _initState()); - static SessionService get to => Get.find(); + static SessionService get to => Injector.instance.get(); - AuthService get _authService => find(); - StorageService get _storageService => find(); - ConfigStateService get _configStateService => find(); + StorageService get _storageService => resolve(); + ConfigStateService get _configStateService => resolve(); + EnvironmentService get _environmentService => resolve(); bool get isAuthenticated { if (_store.state.profile == null || _store.state.token == null) { @@ -32,6 +35,10 @@ class SessionService extends ServiceBase { !_store.state.token!.accessToken.isNullOrWhiteSpace(); } + Session get state { + return _store.state; + } + CurrentTenantDto? get tenant{ return _store.state.tenant; } @@ -61,13 +68,10 @@ class SessionService extends ServiceBase { void _initUpdateStream() { var token$ = _store.sliceState((state) => state.token); - token$.doOnData((_) => _configStateService.refreshAppState()) - .whereNotNull() - .switchMap((_) => Stream.fromFuture(_authService.getProfile())) - .listen((profile) { - var abpConfig = _configStateService.getAll(); + token$ + .switchMap((_) => _configStateService.refreshAppState()) + .listen((abpConfig) { _store.patch((state) { - state.profile = profile; state.tenant = abpConfig.currentTenant; }); }); @@ -99,13 +103,23 @@ class SessionService extends ServiceBase { _store.patch((state) => state.language = language); } - void refreshProfile() { + void setProfile(UserProfile? profile) { + if (profile != null && !profile.avatarUrl.isNullOrWhiteSpace()) { + if (!GetUtils.isURL(profile.avatarUrl!)) { + var environment = _environmentService.getEnvironment(); + var avatarServerPath = environment.remoteServices.getApiUrl('avatar'); + if (!profile.avatarUrl!.startsWith(avatarServerPath)) { + profile.avatarUrl = '$avatarServerPath${profile.avatarUrl}${'?access_token=${token?.accessToken}'}'; + } + } + } + _store.patch((state) { state.profile = profile; }); } - void refreshToken(Token? token) { + void setToken(Token? token) { _store.patch((state) { state.token = token; }); diff --git a/apps/flutter/core/lib/services/storage.service.dart b/apps/flutter/core/lib/services/storage.service.dart index 9cbf11cc9..77b9bc3b1 100644 --- a/apps/flutter/core/lib/services/storage.service.dart +++ b/apps/flutter/core/lib/services/storage.service.dart @@ -1,8 +1,9 @@ -import 'package:get/get.dart'; +import 'package:core/dependency/index.dart'; import 'package:get_storage/get_storage.dart'; import 'service.base.dart'; class GetxStorageService extends StorageService { + GetxStorageService(super._injector); static late GetStorage _storage; static Future init([String container = 'GetStorage']) async { try { @@ -43,9 +44,10 @@ class GetxStorageService extends StorageService { } class StorageService extends ServiceBase { + StorageService(super._injector); static final Map _storage = {}; - static StorageService get to => Get.find(); + static StorageService get to => injector.get(); static T? initStorage(String key, T? Function(String) formater) { return to.getFormat(key, formater); diff --git a/apps/flutter/core/lib/services/subscription.service.dart b/apps/flutter/core/lib/services/subscription.service.dart index b9307f959..672aa2372 100644 --- a/apps/flutter/core/lib/services/subscription.service.dart +++ b/apps/flutter/core/lib/services/subscription.service.dart @@ -1,49 +1,78 @@ import 'dart:async'; -import 'package:rxdart/rxdart.dart'; +import 'package:core/services/service.base.dart'; import 'package:rxdart_ext/rxdart_ext.dart'; -class SubscriptionService { +class SubscriptionService extends ServiceBase { + SubscriptionService(super._injector); final CompositeSubscription _subscription = CompositeSubscription(); - bool get isClosed => _subscription.isDisposed; + @override + void onClose() { + _subscription.clear(); + super.onClose(); + } void addOne(StreamSubscription subscription) { subscription.addTo(_subscription); } - StreamSubscription subscribe( + void subscribeOnce( Stream source$, - [void Function(T value)? next, - void Function(dynamic error)? error] + { + void Function(T value)? next, + void Function(dynamic error)? error, + void Function()? done, + void Function()? cancel, + } ) { - var subscription = source$.listen((value) { - if (next != null) { - next(value); - } - }, onError: (err) { - if (error != null) { - error(err); + StreamSubscription? subscription; + subscription = subscribe(source$, + next: next, + error: error, + cancel: cancel, + done: () { + if (done != null) done(); + closeOne(subscription); } - }); + ); + } + + StreamSubscription subscribe( + Stream source$, + { + void Function(T value)? next, + void Function(dynamic error)? error, + void Function()? done, + void Function()? cancel, + } + ) { + var subscription = source$.doOn( + data: next, + error:(err, stackTrace) { + if (error != null) { + error(err); + } + }, + done: done, + cancel: cancel, + ).listen(null); + subscription.addTo(_subscription); return subscription; } Future closeAll() async { - await _subscription.cancel(); + await _subscription.clear(); } - Future closeOne(StreamSubscription? subscription) async { - await removeOne(subscription); - if (subscription != null) { - await subscription.cancel(); - } + Future closeOne(StreamSubscription? subscription, { bool shouldCancel = true }) async { + await removeOne(subscription, shouldCancel: shouldCancel); } - Future removeOne(StreamSubscription? subscription) async { + Future removeOne(StreamSubscription? subscription, { bool shouldCancel = true }) async { if (subscription == null) return; - await _subscription.remove(subscription); + await _subscription.remove(subscription, shouldCancel: shouldCancel); } Future reset() async { diff --git a/apps/flutter/core/lib/services/theme.service.dart b/apps/flutter/core/lib/services/theme.service.dart index 275b40b3d..aeea4a415 100644 --- a/apps/flutter/core/lib/services/theme.service.dart +++ b/apps/flutter/core/lib/services/theme.service.dart @@ -17,8 +17,10 @@ class ThemeState { } class ThemeService extends ServiceBase { + ThemeService(super._injector); static const String themeKey = '_abp_theme_'; - StorageService get storageService => find(); + + StorageService get _storageService => resolve(); final InternalStore _store = InternalStore(state: ThemeState(Brightness.light, ThemeUtils.lightColorScheme)); @@ -55,13 +57,13 @@ class ThemeService extends ServiceBase { case Brightness.dark: ThemeUtils.currentTheme = ThemeUtils.darkTheme; ThemeUtils.currentColor = ThemeUtils.darkColorScheme; - storageService.setItem(themeKey, 'dark'); + _storageService.setItem(themeKey, 'dark'); Get.changeThemeMode(ThemeMode.dark); return; case Brightness.light: ThemeUtils.currentTheme = ThemeUtils.lightTheme; ThemeUtils.currentColor = ThemeUtils.lightColorScheme; - storageService.setItem(themeKey, 'light'); + _storageService.setItem(themeKey, 'light'); Get.changeThemeMode(ThemeMode.light); return; } diff --git a/apps/flutter/core/lib/services/translation.service.dart b/apps/flutter/core/lib/services/translation.service.dart new file mode 100644 index 000000000..75c4a8cbb --- /dev/null +++ b/apps/flutter/core/lib/services/translation.service.dart @@ -0,0 +1,3 @@ +abstract class TranslationService { + Map> getResources(); +} \ No newline at end of file diff --git a/apps/flutter/core/lib/tokens/abp.tokens.dart b/apps/flutter/core/lib/tokens/abp.tokens.dart index e7790fb51..78df63e57 100644 --- a/apps/flutter/core/lib/tokens/abp.tokens.dart +++ b/apps/flutter/core/lib/tokens/abp.tokens.dart @@ -1,3 +1,3 @@ class AbpTokens { - + static const String application = 'application'; } diff --git a/apps/flutter/core/lib/tokens/http.token.dart b/apps/flutter/core/lib/tokens/http.token.dart index 24192d455..f61a658d4 100644 --- a/apps/flutter/core/lib/tokens/http.token.dart +++ b/apps/flutter/core/lib/tokens/http.token.dart @@ -1,5 +1,5 @@ class HttpTokens { - /// 用户自行处理请求异常,异常程序不进行处理 + /// 忽略错误提示信息 static const String ignoreError = "ignore_error"; /// 请求不携带token static const String ignoreToken = "ignore_token"; diff --git a/apps/flutter/core/lib/tokens/index.dart b/apps/flutter/core/lib/tokens/index.dart index 8d660764e..e412a1cbe 100644 --- a/apps/flutter/core/lib/tokens/index.dart +++ b/apps/flutter/core/lib/tokens/index.dart @@ -1,3 +1,2 @@ export 'abp.tokens.dart'; -export 'http.token.dart'; -export 'notifications.token.dart'; \ No newline at end of file +export 'http.token.dart'; \ No newline at end of file diff --git a/apps/flutter/core/lib/tokens/notifications.token.dart b/apps/flutter/core/lib/tokens/notifications.token.dart deleted file mode 100644 index dbfa4cc24..000000000 --- a/apps/flutter/core/lib/tokens/notifications.token.dart +++ /dev/null @@ -1,8 +0,0 @@ -class NotificationTokens { - /// 通知生产者 - static const String producer = "producer"; - /// 通知消费者 - static const String consumer = "consumer"; - /// 通知订阅者(接收通知数据名称, 与Hub方法同名), 定义便于订阅/取消 - static const String receiver = "get-notification"; -} \ No newline at end of file diff --git a/apps/flutter/core/lib/utils/date.format.utils.dart b/apps/flutter/core/lib/utils/date.format.utils.dart new file mode 100644 index 000000000..2b28c1784 --- /dev/null +++ b/apps/flutter/core/lib/utils/date.format.utils.dart @@ -0,0 +1,7 @@ +import 'package:date_format/date_format.dart'; + +extension DateTimeFormat on DateTime { + String format(List formats, {DateLocale locale = const EnglishDateLocale()}) { + return formatDate(this, formats); + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/utils/environment.utils.dart b/apps/flutter/core/lib/utils/environment.utils.dart new file mode 100644 index 000000000..c6607bbc8 --- /dev/null +++ b/apps/flutter/core/lib/utils/environment.utils.dart @@ -0,0 +1,59 @@ +import 'package:core/dependency/injector.dart'; +import 'package:core/models/environment.dart'; +import 'package:core/services/index.dart'; +import 'package:core/utils/string.extensions.dart'; +import 'package:dio/dio.dart'; + +class EnvironmentUtils { + static Future mergeRemoteEnvironment(Injector injector, Environment environment) { + var restService = injector.get(); + var environmentService = injector.get(); + + var url = environment.remoteEnvironment.url; + var method = environment.remoteEnvironment.method ?? 'GET'; + var headers = environment.remoteEnvironment.headers ?? {}; + if (url.isNullOrWhiteSpace()) { + return Future.value(); + } + + return restService.request( + method: method, + url: url, + options: Options( + headers: headers, + ), + transformer: (res) { + if (res.data == null) return; + var remoteEnv = Environment.fromJson(res.data); + environmentService.setState( + _mergeEnvironments( + environment, + remoteEnv, + environment.remoteEnvironment + ) + ); + } + ); + } + + static Environment _mergeEnvironments( + Environment localEnv, + Environment remoteEnv, + RemoteEnvironmentConfig remoteEnvConfig) + { + switch (remoteEnvConfig.strategy) { + case MergeStrategy.deepmerge: + return localEnv.copyWith( + auth: remoteEnv.auth, + tenant: remoteEnv.tenant, + application: remoteEnv.application, + localization: remoteEnv.localization, + notifications: remoteEnv.notifications, + remoteServices: remoteEnv.remoteServices, + remoteEnvironment: remoteEnv.remoteEnvironment, + ); + case MergeStrategy.overwrite: + default: return remoteEnv; + } + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/utils/http.client.dart b/apps/flutter/core/lib/utils/http.client.dart new file mode 100644 index 000000000..aba518b7d --- /dev/null +++ b/apps/flutter/core/lib/utils/http.client.dart @@ -0,0 +1,3 @@ +abstract class HttpClient { + +} \ No newline at end of file diff --git a/apps/flutter/core/lib/utils/index.dart b/apps/flutter/core/lib/utils/index.dart index 07f1fe796..fe2eb5beb 100644 --- a/apps/flutter/core/lib/utils/index.dart +++ b/apps/flutter/core/lib/utils/index.dart @@ -1,3 +1,4 @@ +export 'environment.utils.dart'; export 'internal.store.dart'; export 'localization.utils.dart'; export 'logging.dart'; diff --git a/apps/flutter/core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/core/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/core/pubspec.yaml b/apps/flutter/core/pubspec.yaml index 85b344404..e190b41a1 100644 --- a/apps/flutter/core/pubspec.yaml +++ b/apps/flutter/core/pubspec.yaml @@ -12,17 +12,16 @@ dependencies: flutter: sdk: flutter - dio: + dio: ^5.2.0+1 - get: - get_storage: - rxdart: - rxdart_ext: - logger: - logging: - signalr_netcore: ^1.3.4 + get: ^4.6.5 + get_storage: ^2.1.1 + rxdart: ^0.27.7 + rxdart_ext: ^0.2.9 + logger: ^1.4.0 + logging: ^1.2.0 json_annotation: ^4.8.1 - flutter_app_environment: ^1.0.1 + date_format: ^2.0.7 dev_dependencies: flutter_test: diff --git a/apps/flutter/core/test/abp_storage_service.test.dart b/apps/flutter/core/test/abp_storage_service.test.dart index ebbf7bb40..1397e6f6b 100644 --- a/apps/flutter/core/test/abp_storage_service.test.dart +++ b/apps/flutter/core/test/abp_storage_service.test.dart @@ -1,13 +1,13 @@ import 'package:core/core.module.dart'; +import 'package:core/dependency/index.dart'; import 'package:core/services/storage.service.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:get/get.dart'; void main() { test('set storage', () async { var module = CoreModule(); await module.initAsync(); - var storage = Get.find(); + var storage = injector.get(); storage.setItem('key', 'value'); expect(storage.getItem('key'), 'value'); diff --git a/apps/flutter/dev_app/README.md b/apps/flutter/dev_app/README.md index 31b40a3a7..ca9608d07 100644 --- a/apps/flutter/dev_app/README.md +++ b/apps/flutter/dev_app/README.md @@ -15,36 +15,113 @@ For help getting started with Flutter development, view the [online documentation](https://docs.flutter.dev/), which offers tutorials, samples, guidance on mobile development, and a full API reference. -## Environment - -* **baseUrl**: 服务器连接地址(必输) -* **clientId**: 客户端标识(必输) -* **clientSecret**: 客户端密钥(可选) -* **authority**: 身份认证服务器地址(必输) -* **uploadFilesUrl**: 上传文件路径(可选) -* **staticFilesUrl**: 静态文件路径(可选) -* **tenantKey**: 多租户标识(可选) -* **defaultLanguage**: 应用程序默认语言, 优先级低于用户配置(可选) -* **notifications**: 通知相关设置(可选) -* ***android***: android端通知设置(可选) -* ***channelId***: 通道标识(配置了android节点后为必输) -* ***channelName***: 通道名称(配置了android节点后为必输) -* ***channelDescription***: 通道说明(可选) -* ***linux***: linux端通知设置(可选) -* ***defaultActionName***: 默认点击方法名称(配置了linux节点后为必输) -* ***darwin***: iOS/Mac os端通知设置(可选) +## Translations +### 预制本地化文档 +* [English](./translation.json) +* [简体中文](./translation.zh-Hans.json) + +### 使用方法 + +- 本地文件 + + **替换 [AbpTranslations](./lib/utils/localization.dart) 中keys为如下格式:** + + ```json + { + "zh-Hans": { + "Center:Feedback": "意见反馈", + "Center:Help": "在线帮助", + "Center:Info": "关于", + ...其他本地化内容 + }, + "en": { + "Center:Feedback": "Feedback", + "Center:Help": "Help", + "Center:Info": "Info", + ...other localizations, + }, + } + ``` + +- 后台服务 + + **将预制的本地化文档复制到后台服务的本地化目录即可, 具体见abp多语言文档** + +## Environment 环境配置 + +> **application** 应用程序配置 +>> *name* 应用程序名称 + +> **auth** 身份认证服务器配置 +>> *authority* 身份认证服务器地址 +>> *clientId* 客户端标识 +>> *clientSecret* 客户端密钥 + +> **tenant** 多租户配置 +>> *tenantKey* 多租户标识 + +> **localization** 国际化配置 +>> *defaultLanguage* 应用程序默认语言 + +> **remoteServices** 远程服务配置 +>> default 默认连接配置 必须指定 +>>> url 连接地址 +>>> rootNamespace 根命名空间(保留配置) + +>> avatar 头像接口配置(如果用户头像设定为相对路径, 需要指定接口地址前缀) +>>> url 连接地址 + +> **remoteEnvironment** 远程环境配置(按照给定的应用策略替换当前环境配置) +>> *url* 连接地址(从此连接拉取配置信息) +>> *method* 请求方法 +>> *headers* 请求头 +>> *strategy* 应用策略,deepmerge(合并)、overwrite(替换) + +> **notifications** 通知相关设置 +>> *android* android端通知设置(可选) +>>> - *channelId*: 通道标识(配置了android节点后为必输) +>>> - *channelName*: 通道名称(配置了android节点后为必输) +>>> - *channelDescription*: 通道说明(可选) + +>> *linux* linux端通知设置(可选) +>>> - *defaultActionName*: 默认点击方法名称(配置了linux节点后为必输) + +>> *darwin* iOS/Mac os端通知设置(可选) + + +# 配置示例 +[demo.json](./res/config/demo.json) ```json { - "baseUrl": "http://127.0.0.1:30000", - "clientId": "abp-flutter", - "clientSecret": "1q2w3e*", - "authority": "http://127.0.0.1:30000", - "uploadFilesUrl": "", - "staticFilesUrl": "", - "tenantKey": "__tenant", - "defaultLanguage": "en", + "application": { + "name": "app-flutter" + }, + "auth": { + "clientId": "abp-flutter", + "clientSecret": "1q2w3e*", + "authority": "http://127.0.0.1:30000" + }, + "tenant": { + "tenantKey": "__tenant" + }, + "localization": { + "defaultLanguage": "zh-Hans" + }, + "remoteServices": { + "default": { + "url": "http://127.0.0.1:30000" + }, + "avatar": { + "url": "http://127.0.0.1:30000/api/files/static/users/p/" + } + }, + "remoteEnvironment": { + "url": "", + "strategy": "deepmerge" + }, "notifications": { + "serverUrl": "http://127.0.0.1:30000/signalr-hubs/notifications", "android": { "channelId": "abp-flutter", "channelName": "abp-flutter", diff --git a/apps/flutter/dev_app/lib/handlers/error.handler.dart b/apps/flutter/dev_app/lib/handlers/error.handler.dart new file mode 100644 index 000000000..175fb282e --- /dev/null +++ b/apps/flutter/dev_app/lib/handlers/error.handler.dart @@ -0,0 +1,106 @@ +import 'dart:async'; + +import 'package:account/pages/route.name.dart'; +import 'package:core/dependency/index.dart'; +import 'package:core/models/abp.error.dart'; +import 'package:core/services/index.dart'; +import 'package:core/tokens/index.dart'; +import 'package:dev_app/utils/loading.dart'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:rxdart/rxdart.dart'; + +class ErrorHandler { + ErrorHandler(Injector injector): + _sessionService = injector.get(), + _errorReporter = injector.get(); + + final SessionService _sessionService; + final ErrorReporterService _errorReporter; + + StreamSubscription listenToRestError() { + return _errorReporter.getReporter$() + .whereType() + .where(_filterRestErrors) + .listen(_handleError); + } + + bool _filterRestErrors(DioException exception) { + return !exception.requestOptions.extra.containsKey(HttpTokens.ignoreError); + } + + void _handleError(DioException exception) { + if (exception.response == null) return; + var errorTitle = 'DefaultErrorMessage'.tr; + var errorMessage = 'DefaultErrorMessageDetail'.tr; + if (exception.response!.headers['abp-tenant-resolve-error']?.isEmpty == false) { + _sessionService.setToken(null); + return; + } + + if (exception.response!.headers['_abperrorformat']?.isEmpty == false) { + _showErrorWithRequestBody(exception); + } else { + switch (exception.response!.statusCode) { + case 400: + if (exception.response?.data?['error'] != null) { + errorTitle = exception.response!.data['error']; + } + if (exception.response?.data?['error_description'] != null) { + errorMessage = exception.response!.data['error_description']; + } + case 401: + errorTitle = 'DefaultErrorMessage401'.tr; + errorMessage = 'DefaultErrorMessage401Detail'.tr; + _showError(errorTitle, errorMessage, () => Get.toNamed(AccountRoutes.login)); + return; + case 403: + errorTitle = 'DefaultErrorMessage403'.tr; + errorMessage = 'DefaultErrorMessage403Detail'.tr; + break; + case 404: + errorTitle = 'DefaultErrorMessage404'.tr; + errorMessage = 'DefaultErrorMessage404Detail'.tr; + break; + case 500: + errorTitle = '500Message'.tr; + errorMessage = 'DefaultErrorMessage'.tr; + break; + default: + } + _showError(errorTitle, errorMessage); + } + } + + void _showErrorWithRequestBody(DioException err) { + var errorJson = err.response!.data['error']; + var remoteServiceErrorInfo = RemoteServiceErrorInfo.fromJson(errorJson); + var errorTitle = remoteServiceErrorInfo.message; + var errorMessage = remoteServiceErrorInfo.details ?? errorTitle; + if (remoteServiceErrorInfo.validationErrors?.isEmpty == false) { + errorMessage += remoteServiceErrorInfo.validationErrors!.map((v) => v.message).join('\n'); + } + _showError(errorTitle, errorMessage); + } + + void _showError(String title, String message, [VoidCallback? callback]) { + //Loading.toast(message); + if (Get.isOverlaysOpen == false) { + Loading.toast(message); + if (callback != null) { + callback(); + } + return; + } + Get.defaultDialog( + title: title, + content: Text(message), + onConfirm: () { + if (callback != null) { + callback(); + } + }, + ); + } +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/handlers/index.dart b/apps/flutter/dev_app/lib/handlers/index.dart new file mode 100644 index 000000000..148a4241f --- /dev/null +++ b/apps/flutter/dev_app/lib/handlers/index.dart @@ -0,0 +1 @@ +export 'error.handler.dart'; \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/interceptors/api.append.header.interceptor.dart b/apps/flutter/dev_app/lib/interceptors/api.append.header.interceptor.dart index a8261faf6..96896eaee 100644 --- a/apps/flutter/dev_app/lib/interceptors/api.append.header.interceptor.dart +++ b/apps/flutter/dev_app/lib/interceptors/api.append.header.interceptor.dart @@ -1,4 +1,4 @@ -import 'package:core/config/index.dart'; +import 'package:core/services/environment.service.dart'; import 'package:core/services/session.service.dart'; import 'package:core/utils/string.extensions.dart'; import 'package:dio/dio.dart'; @@ -6,13 +6,13 @@ import 'package:dio/dio.dart'; class AppendHeaderInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { - var language = SessionService.to.currentLanguage; - if (!language.isNullOrWhiteSpace()) { - options.headers['Accept-Language'] = language; + var session = SessionService.to.state; + if (!session.language.isNullOrWhiteSpace()) { + options.headers['Accept-Language'] = session.language; } - var tenant = SessionService.to.tenant; - if (tenant != null && tenant.isAvailable == true) { - options.headers[Environment.current.tenantKey ?? '__tenant'] = tenant.id; + if (session.tenant != null && session.tenant!.isAvailable == true) { + var environment = EnvironmentService.to.getEnvironment(); + options.headers[environment.tenant.tenantKey ?? '__tenant'] = session.tenant!.id; } return handler.next(options); } diff --git a/apps/flutter/dev_app/lib/interceptors/api.exception.interceptor.dart b/apps/flutter/dev_app/lib/interceptors/api.exception.interceptor.dart index c0905e35c..cf273b8b7 100644 --- a/apps/flutter/dev_app/lib/interceptors/api.exception.interceptor.dart +++ b/apps/flutter/dev_app/lib/interceptors/api.exception.interceptor.dart @@ -1,37 +1,14 @@ -import 'package:dev_app/utils/loading.dart'; -import 'package:core/tokens/http.token.dart'; +import 'package:core/services/error.reporter.service.dart'; import 'package:dio/dio.dart'; -import 'package:get/get.dart'; class ExceptionInterceptor extends Interceptor { - ExceptionInterceptor(); + ExceptionInterceptor(this._errorReporterService); + + final ErrorReporterService _errorReporterService; @override void onError(DioException err, ErrorInterceptorHandler handler) { - if (err.requestOptions.extra.containsKey(HttpTokens.ignoreError)) { - return handler.next(err); - } - var errorMessage = err.message ?? '网络请求失败'; - if (err.response != null) { - if (err.response!.statusCode == 401) { - errorMessage = '您的会话已超时, 请重新登录'; - _showErrorToast(errorMessage); - Get.toNamed('/account/login'); - return; - } - - if (err.response?.data?['error_description'] != null) { - errorMessage = err.response!.data['error_description']; - _showErrorToast(errorMessage); - return handler.next(err); - } - } - - _showErrorToast(errorMessage); + _errorReporterService.reportError(err); return handler.next(err); } - - void _showErrorToast(String errorMessage) { - Loading.toast(errorMessage); - } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/main.dart b/apps/flutter/dev_app/lib/main.dart index 3e3a9532d..f99928b23 100644 --- a/apps/flutter/dev_app/lib/main.dart +++ b/apps/flutter/dev_app/lib/main.dart @@ -1,8 +1,9 @@ +import 'package:core/dependency/index.dart'; +import 'package:core/utils/theme.utils.dart'; +import 'package:core/utils/logging.dart'; import 'package:dev_app/main.module.dart'; import 'package:dev_app/utils/localization.dart'; -import 'package:core/utils/theme.utils.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:core/utils/logging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; @@ -19,7 +20,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - MainModule module = Get.find(); + MainModule module = injector.get(); return GetMaterialApp( theme: ThemeUtils.lightTheme, darkTheme: ThemeUtils.darkTheme, @@ -29,7 +30,7 @@ class MyApp extends StatelessWidget { debugShowMaterialGrid: false, enableLog: true, builder: EasyLoading.init(), - translations: AbpTranslations(Get.find()), + translations: AbpTranslations(injector.get()), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, @@ -42,7 +43,11 @@ class MyApp extends StatelessWidget { logger.info(text); } }, - //supportedLocales: AbpLocalizations.supportedLocales, + supportedLocales: const [ + Locale('zh', 'Hans'), + Locale('zh', 'CN'), + Locale('en', 'US'), + ], ); } } diff --git a/apps/flutter/dev_app/lib/main.module.dart b/apps/flutter/dev_app/lib/main.module.dart index a8dabfaea..a0dc8c9b3 100644 --- a/apps/flutter/dev_app/lib/main.module.dart +++ b/apps/flutter/dev_app/lib/main.module.dart @@ -1,25 +1,30 @@ +import 'package:components/index.dart'; import 'package:dev_app/pages/index.dart'; import 'package:dev_app/services/index.dart'; +import 'package:dev_app/utils/initial.utils.dart'; import 'package:dev_app/utils/loading.dart'; import 'package:account/index.dart'; -import 'package:components/index.dart'; import 'package:core/modularity/index.dart'; import 'package:core/index.dart'; import 'package:dio/dio.dart'; -import 'package:flex_color_scheme/flex_color_scheme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:notifications/notifications.module.dart'; +import 'package:notifications/index.dart'; +import 'package:oauth/index.dart'; +import 'package:platforms/index.dart'; +import 'handlers/error.handler.dart'; import 'interceptors/index.dart'; class MainModule extends Module { @override List get dependencies => [ - CoreModule(), + ComponentsModule(), + OAuthModule(), AccountModule(), NotificationsModule(), + PlatformModule(), ]; @override @@ -39,108 +44,60 @@ class MainModule extends Module { ...SystemRoute.routes, ]; - @override - Future configureServicesAsync() async { - - await injectAsync(() async { - var service = FlutterLocalNotificationsSendService(); - await service.initAsync(); - return service; - }, permanent: true); - - await super.configureServicesAsync(); - } - @override void configureServices() { inject(this); + inject(FlutterApplicationInitialService()); - inject(SignalrService('${Environment.current.baseUrl}/signalr-hubs/notifications'), - tag: NotificationTokens.producer, - permanent: true); + lazyInject((injector) => ErrorHandler(injector)); + lazyInject((injector) { + var environmentService = get(); + var environment = environmentService.getEnvironment(); - lazyInject(() { - var dio = Dio(BaseOptions( - baseUrl: Environment.current.baseUrl, - )); + if (environment.notifications?.serverUrl.isNullOrWhiteSpace() == true) { + return NullSignalrService(); + } + + return AspNetCoreSignalrService(environment.notifications!.serverUrl!); + }, tag: NotificationTokens.producer); + lazyInject((injector) { + var environmentService = injector.get(); + var dio = Dio(); dio.interceptors.add(LoggerInterceptor()); - dio.interceptors.add(OAuthApiInterceptor()); + dio.interceptors.add(ApiAuthorizationInterceptor()); dio.interceptors.add(AppendHeaderInterceptor()); - dio.interceptors.add(AbpWrapperRemoteServiceErrorInterceptor()); + //dio.interceptors.add(AbpWrapperRemoteServiceErrorInterceptor()); dio.interceptors.add(WrapperResultInterceptor()); - dio.interceptors.add(ExceptionInterceptor()); + dio.interceptors.add(ExceptionInterceptor(get())); - return RestService(dio: dio); + return RestService(dio, environmentService); + }); + lazyInject((ioc) { + var environmentService = get(); + var environment = environmentService.getEnvironment(); + // 使用资源文件中的本地化文档 + if (environment.localization.useLocalResources == true) { + return TranslationResService(ioc); + } + // 使用本地化服务提供的本地化支持 + return ioc.get(); }, fenix: true); - - lazyInject(() => OAuthService( - clientId: Environment.current.clientId, - clientSecret: Environment.current.clientSecret - ), fenix: true); } @override Future>> initAsync() async { WidgetsFlutterBinding.ensureInitialized(); await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); - await Environment.initAsync(); Loading(); + inject(injector, permanent: true); var moduleRoutes = await super.initAsync(); - initComponent(); - initThemeData(); - - return moduleRoutes; - } + await InitialUtils.initialState(get()); - void initComponent() { - if (!Environment.current.staticFilesUrl.isNullOrWhiteSpace()) { - AvatarConfig.baseUrl = Environment.current.staticFilesUrl!; - } else { - AvatarConfig.baseUrl = '${Environment.current.baseUrl}/api/files/static/users/p/'; - } - } + InitialUtils.initComponent(get()); + //InitialUtils.initThemeData(); - void initThemeData() { - ThemeUtils.lightTheme = FlexThemeData.light( - scheme: FlexScheme.amber, - surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, - blendLevel: 7, - subThemesData: const FlexSubThemesData( - blendOnLevel: 10, - blendOnColors: false, - useTextTheme: true, - useM2StyleDividerInM3: true, - thinBorderWidth: 0.5, - thickBorderWidth: 0.5, - defaultRadius: 0.0, - cardRadius: 6.0, - ), - visualDensity: FlexColorScheme.comfortablePlatformDensity, - useMaterial3: true, - swapLegacyOnMaterial3: true, - // To use the Playground font, add GoogleFonts package and uncomment - // fontFamily: GoogleFonts.notoSans().fontFamily, - ); - ThemeUtils.darkTheme = FlexThemeData.dark( - scheme: FlexScheme.amber, - surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, - blendLevel: 13, - subThemesData: const FlexSubThemesData( - blendOnLevel: 20, - useTextTheme: true, - useM2StyleDividerInM3: true, - thinBorderWidth: 0.5, - thickBorderWidth: 0.5, - defaultRadius: 0.0, - cardRadius: 6.0, - ), - visualDensity: FlexColorScheme.comfortablePlatformDensity, - useMaterial3: true, - swapLegacyOnMaterial3: true, - // To use the Playground font, add GoogleFonts package and uncomment - // fontFamily: GoogleFonts.notoSans().fontFamily, - ); + return moduleRoutes; } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/models/translation.state.dart b/apps/flutter/dev_app/lib/models/translation.state.dart new file mode 100644 index 000000000..73846161a --- /dev/null +++ b/apps/flutter/dev_app/lib/models/translation.state.dart @@ -0,0 +1,8 @@ +class TranslationState { + TranslationState({ + this.language, + this.translations = const {}, + }); + String? language; + Map> translations; +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/center/settings/controller.dart b/apps/flutter/dev_app/lib/pages/center/settings/controller.dart index e28e670e7..92b7493ea 100644 --- a/apps/flutter/dev_app/lib/pages/center/settings/controller.dart +++ b/apps/flutter/dev_app/lib/pages/center/settings/controller.dart @@ -1,4 +1,5 @@ import 'package:dev_app/pages/center/settings/state.dart'; +import 'package:core/dependency/index.dart'; import 'package:core/services/session.service.dart'; import 'package:core/services/theme.service.dart'; import 'package:flutter/material.dart'; @@ -6,8 +7,8 @@ import 'package:flutter_picker/flutter_picker.dart'; import 'package:get/get.dart'; class CenterSettingsController extends GetxController { - SessionService get sessionService => Get.find(); - ThemeService get themeService => Get.find(); + SessionService get sessionService => injector.get(); + ThemeService get themeService => injector.get(); final Rx _state = Rx(CenterState(false)); CenterState get state => _state.value; @@ -55,8 +56,8 @@ class CenterSettingsController extends GetxController { ), selecteds: [themeModeIndex], title: Text('Label:Theme'.tr), - cancelText: 'Lable:Cancel'.tr, - confirmText: 'Lable:Confirm'.tr, + cancelText: 'Label:Cancel'.tr, + confirmText: 'Label:Confirm'.tr, height: 210, itemExtent: 40, selectedTextStyle: const TextStyle(color: Colors.blue), diff --git a/apps/flutter/dev_app/lib/pages/main/binding.dart b/apps/flutter/dev_app/lib/pages/main/binding.dart index 791d2bfdd..3c8d55ea5 100644 --- a/apps/flutter/dev_app/lib/pages/main/binding.dart +++ b/apps/flutter/dev_app/lib/pages/main/binding.dart @@ -1,5 +1,6 @@ +import 'package:core/dependency/index.dart'; import 'package:core/services/subscription.service.dart'; -import 'package:core/tokens/index.dart'; +import 'package:notifications/tokens/index.dart'; import 'package:get/get.dart'; import 'controller.dart'; @@ -8,6 +9,6 @@ class MainBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => MainController()); - Get.lazyPut(() => SubscriptionService(), tag: NotificationTokens.consumer); + Get.lazyPut(() => SubscriptionService(Injector.instance), tag: NotificationTokens.consumer); } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/main/controller.dart b/apps/flutter/dev_app/lib/pages/main/controller.dart index 9c08eb7f6..ccfccf474 100644 --- a/apps/flutter/dev_app/lib/pages/main/controller.dart +++ b/apps/flutter/dev_app/lib/pages/main/controller.dart @@ -1,25 +1,30 @@ +import 'package:core/dependency/index.dart'; +import 'package:core/abstracts/signalr.service.dart'; +import 'package:core/services/environment.service.dart'; import 'package:core/services/notification.send.service.dart'; +import 'package:dev_app/handlers/index.dart'; import 'package:get/get.dart'; -import 'package:core/config/index.dart'; import 'package:core/services/session.service.dart'; -import 'package:core/services/signalr.service.dart'; import 'package:core/services/subscription.service.dart'; -import 'package:core/tokens/index.dart'; import 'package:core/utils/index.dart'; import 'package:notifications/models/index.dart'; +import 'package:notifications/tokens/index.dart'; class MainController extends GetxController { final RxInt _pageIndex = RxInt(0); int get currentIndex => _pageIndex.value; - SessionService get _sessionService => Get.find(); - SubscriptionService get _subscriptionService => Get.find(tag: NotificationTokens.consumer); - SignalrService get _signalrService => Get.find(tag: NotificationTokens.producer); - NotificationSendService get _notificationSendService => Get.find(); + SessionService get _sessionService => injector.get(); + SubscriptionService get _subscriptionService => injector.get(tag: NotificationTokens.consumer); + SignalrService get _signalrService => injector.get(tag: NotificationTokens.producer); + NotificationSendService get _notificationSendService => injector.get(); + EnvironmentService get _environmentService => injector.get(); + ErrorHandler get _errorHandler => injector.get(); @override void onInit() async { super.onInit(); + _subscriptionService.addOne(_errorHandler.listenToRestError()); _subscriptionService.addOne(_signalrService.onClose(logger.debug)); _subscriptionService.addOne(_signalrService.onReconnected(logger.debug)); _subscriptionService.addOne(_signalrService.onReconnecting(logger.debug)); @@ -27,13 +32,13 @@ class MainController extends GetxController { _subscriptionService.subscribe( // 订阅SignalR Hub _signalrService.subscribe(NotificationTokens.receiver), - (message) async { + next: (message) async { for (var data in message.data) { if (data == null) continue; // 解析通知数据 var notification = NotificationInfo.fromJson(data as dynamic); // 格式化为移动端可识别通知数据 - var payload = NotificationPaylod.fromData(notification.data); + var payload = NotificationPaylod.fromNotification(notification); // 发布本地通知 await _notificationSendService.send( payload.title, @@ -52,7 +57,8 @@ class MainController extends GetxController { } }); if (_sessionService.currentLanguage.isNullOrWhiteSpace()) { - _sessionService.setLanguage(Environment.current.defaultLanguage ?? 'en'); + var environment = _environmentService.getEnvironment(); + _sessionService.setLanguage(environment.localization.defaultLanguage ?? 'en'); } } diff --git a/apps/flutter/dev_app/lib/pages/public/center/controller.dart b/apps/flutter/dev_app/lib/pages/public/center/controller.dart index e33b8f7ca..653c1a1f7 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/controller.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/controller.dart @@ -1,11 +1,15 @@ +import 'package:account/pages/route.name.dart'; import 'package:core/models/auth.dart'; +import 'package:core/dependency/index.dart'; import 'package:core/services/session.service.dart'; +import 'package:dev_app/pages/center/route.name.dart'; import 'package:get/get.dart'; +import 'package:notifications/pages/route.name.dart'; import 'state.dart'; class CenterController extends GetxController { - SessionService get sessionService => Get.find(); + SessionService get sessionService => injector.get(); final Rx _state = Rx(CenterState(isAuthenticated: false)); CenterState get state => _state.value; @@ -18,26 +22,45 @@ class CenterController extends GetxController { void onInit() { super.onInit(); sessionService.getProfile$() - .listen((event) { + .listen((profile) { _state.update((val) { - val?.profile = event; + val?.profile = profile; val?.isAuthenticated = sessionService.isAuthenticated; }); }); sessionService.getToken$() - .listen((event) { + .listen((token) { _state.update((val) { - val?.token = event; + val?.token = token; }); }); } - String get userName { - return !isAuthenticated ? 'Label:Anonymous'.tr : profile!.userName; + void onClickProfile() { + if (!state.isAuthenticated) { + return redirectToRoute(AccountRoutes.login); + } + redirectToRoute(AccountRoutes.profile); } - String get phoneNumber { - return !isAuthenticated ? '' : profile!.phoneNumber ?? 'Label:PhoneNumberNotBound'.tr; + void onClickFeedback() { + + } + + void onClickHelp() { + + } + + void onClickInfo() { + + } + + void onClickMessage() { + redirectToRoute(NotificationRoutes.notifies); + } + + void onSettings() { + redirectToRoute(CenterRoutes.settings); } void redirectToRoute(String route) { diff --git a/apps/flutter/dev_app/lib/pages/public/center/state.dart b/apps/flutter/dev_app/lib/pages/public/center/state.dart index ec29fb9a6..b19bb2c89 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/state.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/state.dart @@ -1,4 +1,5 @@ import 'package:core/models/auth.dart'; +import 'package:get/get.dart'; class CenterState { CenterState({ @@ -9,4 +10,12 @@ class CenterState { Token? token; UserProfile? profile; bool isAuthenticated; + + String get userName { + return !isAuthenticated ? 'Label:Anonymous'.tr : profile!.userName; + } + + String get phoneNumber { + return !isAuthenticated ? '' : profile!.phoneNumber ?? 'Label:PhoneNumberNotBound'.tr; + } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/center/view.dart b/apps/flutter/dev_app/lib/pages/public/center/view.dart index d0e5b2794..465547611 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/view.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/view.dart @@ -1,6 +1,3 @@ -import 'package:core/services/notification.send.service.dart'; -import 'package:dev_app/pages/center/route.name.dart'; -import 'package:account/pages/route.name.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -21,37 +18,20 @@ class CenterPage extends GetView { height: 100, margin: const EdgeInsets.only(top: 130, left: 20, right: 20), child: Obx(() => UserCard( - avatarUrl: controller.profile?.avatarUrl, - takeToken: controller.token?.accessToken, - userName: controller.userName, - phoneNumber: controller.phoneNumber, - onTap: () { - if (!controller.isAuthenticated) { - controller.redirectToRoute(AccountRoutes.login); - } - else - { - controller.redirectToRoute(AccountRoutes.profile); - } - }, + state: controller.state, + onTap: controller.onClickProfile, )), ), ], ), Container( - margin: const EdgeInsets.only(top: 20, left: 20, right: 20), + margin: const EdgeInsets.only(top: 10, left: 20, right: 20), child: ActionCard( - onHelp: () { - //controller.redirectToRoute('/center/help'); - }, - onFeedback: () { - //controller.redirectToRoute('/center/feedback'); - }, - onSettings: () => controller.redirectToRoute(CenterRoutes.settings), - onInfo: () async { - var service = Get.find(); - await service.send('测试通知', '测试内容', '测试载体'); - }, + onHelp: controller.onClickHelp, + onFeedback: controller.onClickFeedback, + onMessages: controller.onClickMessage, + onSettings: controller.onSettings, + onInfo: controller.onClickInfo, )), ], ); diff --git a/apps/flutter/dev_app/lib/pages/public/center/widget/action_card.dart b/apps/flutter/dev_app/lib/pages/public/center/widget/action_card.dart index e7845255e..ffa131950 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/widget/action_card.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/widget/action_card.dart @@ -8,12 +8,14 @@ class ActionCard extends StatelessWidget { this.onHelp, this.onFeedback, this.onSettings, + this.onMessages, this.onInfo, }); final VoidCallback? onHelp; final VoidCallback? onFeedback; final VoidCallback? onSettings; + final VoidCallback? onMessages; final VoidCallback? onInfo; @override @@ -33,6 +35,12 @@ class ActionCard extends StatelessWidget { prefixIconColor: Colors.orange, onTap: onFeedback, ), + _actionButton( + title: 'Center:Messages'.tr, + prefixIcon: Icons.message, + prefixIconColor: Colors.cyan, + onTap: onMessages, + ), _actionButton( title: 'Center:Settings'.tr, prefixIcon: Icons.settings, diff --git a/apps/flutter/dev_app/lib/pages/public/center/widget/user_card.dart b/apps/flutter/dev_app/lib/pages/public/center/widget/user_card.dart index 8fa3bfb00..a9433ab4f 100644 --- a/apps/flutter/dev_app/lib/pages/public/center/widget/user_card.dart +++ b/apps/flutter/dev_app/lib/pages/public/center/widget/user_card.dart @@ -1,20 +1,16 @@ import 'package:components/index.dart'; import 'package:flutter/material.dart'; +import '../state.dart'; + class UserCard extends StatelessWidget { const UserCard({ super.key, - required this.userName, - required this.phoneNumber, - this.avatarUrl, - this.takeToken, + required this.state, this.onTap, }); - final String userName; - final String phoneNumber; - final String? avatarUrl; - final String? takeToken; + final CenterState state; final VoidCallback? onTap; @override @@ -29,9 +25,9 @@ class UserCard extends StatelessWidget { margin: const EdgeInsets.only(left: 10), width: 50, child: Avatar( - url: avatarUrl, - hintText: userName, - takeToken: takeToken, + url: state.profile?.avatarUrl, + hintText: state.userName, + takeToken: state.token?.accessToken, ), ), Container( @@ -40,12 +36,12 @@ class UserCard extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(userName, + Text(state.userName, style: Theme.of(context).textTheme.titleMedium, ), Opacity( opacity: 0.6, - child: Text(phoneNumber, + child: Text(state.phoneNumber, style: Theme.of(context).textTheme.bodySmall, ), ), diff --git a/apps/flutter/dev_app/lib/pages/public/home/controller.dart b/apps/flutter/dev_app/lib/pages/public/home/controller.dart index 751849dfe..0e8bd7cdd 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/controller.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/controller.dart @@ -1,5 +1,30 @@ import 'package:get/get.dart'; +import 'package:core/dependency/index.dart'; +import 'package:platforms/services/index.dart'; + +import 'state.dart'; class HomeController extends GetxController { - + MenuStateService get _menuStateService => injector.get(); + FavoriteMenuStateService get _favoriteMenuStateService => injector.get(); + + final Rx _state = Rx(HomeState()); + HomeState get state => _state.value; + + @override + void onInit() { + super.onInit(); + // _menuStateService.getMyMenus$() + // .listen((menus) { + // _state.update((val) { + // val?.menus = menus; + // }); + // }); + // _favoriteMenuStateService.getFavoriteMenus$() + // .listen((menus) { + // _state.update((val) { + // val?.favoriteMenus = menus; + // }); + // }); + } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/state.dart b/apps/flutter/dev_app/lib/pages/public/home/state.dart new file mode 100644 index 000000000..a810abe02 --- /dev/null +++ b/apps/flutter/dev_app/lib/pages/public/home/state.dart @@ -0,0 +1,10 @@ +import 'package:platforms/modes/menu.dto.dart'; + +class HomeState { + HomeState({ + this.menus = const [], + this.favoriteMenus = const [], + }); + List menus; + List favoriteMenus; +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/view.dart b/apps/flutter/dev_app/lib/pages/public/home/view.dart index 3d28ce29a..5dcc92008 100644 --- a/apps/flutter/dev_app/lib/pages/public/home/view.dart +++ b/apps/flutter/dev_app/lib/pages/public/home/view.dart @@ -1,15 +1,46 @@ +import 'package:components/index.dart'; +import 'package:dev_app/pages/public/home/widget/search.dart'; import 'package:flutter/material.dart'; import 'controller.dart'; -import 'package:get/get.dart'; -class HomePage extends GetView { +class HomePage extends BasePage { const HomePage({super.key}); @override Widget build(BuildContext context) { - return Center( - child: Text('Page:Home'.tr), + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.background, + title: TextButton( + style: ButtonStyle( + backgroundColor: MaterialStatePropertyAll(Theme.of(context).cardColor), + shape: MaterialStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))) + ), + onPressed: () { + showSearch(context: context, delegate: SearchBarDelegate(menus: bloc.state.menus)); + }, + child: const Row( + children: [ + Icon(Icons.search), + Expanded(child: Text('搜索功能')) + ], + ), + ), + ), + body: Column( + children: [ + Expanded( + child: ListView.builder( + itemCount: bloc.state.favoriteMenus.length, + itemBuilder: (context, index) { + var favoriteMenu = bloc.state.favoriteMenus[index]; + return Text(favoriteMenu.displayName ?? favoriteMenu.name); + }, + ), + ), + ], + ), ); } } \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart b/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart new file mode 100644 index 000000000..99c8e4998 --- /dev/null +++ b/apps/flutter/dev_app/lib/pages/public/home/widget/search.dart @@ -0,0 +1,135 @@ +import 'package:core/index.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:platforms/modes/menu.dto.dart'; + +class SearchBarDelegate extends SearchDelegate { + SearchBarDelegate({ + this.menus = const [], + }); + final List menus; + + @override + List? buildActions(BuildContext context) { + Widget button = IconButton( + onPressed: () { + query = ""; + showSuggestions(context); + }, + icon: const Icon(Icons.clear), + ); + + return [button]; + } + + @override + Widget? buildLeading(BuildContext context) { + return IconButton( + onPressed: () { + close(context, "error"); + }, + icon: AnimatedIcon( + icon: AnimatedIcons.menu_arrow, + progress: transitionAnimation, + ), + ); + } + + @override + Widget buildResults(BuildContext context) { + List results = []; + if (!query.isNullOrWhiteSpace()) { + results = menus.where((menu) { + if (menu.displayName.contains(query) == true) { + return true; + } + if (menu.name.contains(query)) { + return true; + } + return menu.description?.contains(query) == true; + }).map((menu) { + return Padding( + padding: const EdgeInsets.all(10), + child: InkWell( + child: Text(menu.displayName), + onTap: () { + Get.toNamed(menu.path); + }, + ), + ); + }).toList(); + } + if (results.isNotEmpty) { + return Column( + children: results, + ); + } + return const Center( + child: Text('没有结果'), + ); + } + + @override + Widget buildSuggestions(BuildContext context) { + List suggestions = []; + if (!query.isNullOrWhiteSpace()) { + suggestions = menus.where((menu) { + if (menu.displayName.contains(query) == true) { + return true; + } + if (menu.name.contains(query)) { + return true; + } + return menu.description?.contains(query) == true; + }).map((menu) => menu.displayName).toList(); + } + + return ListView.builder( + itemCount: suggestions.length, + itemBuilder: (BuildContext context, int index) { + var suggest = suggestions[index]; + return InkWell( + child: ListTile( + title: RichText( + text: TextSpan( + children: _buildSuggestions(suggest), + ), + ), + ), + onTap: () { + query = suggest; + showResults(context); + }, + ); + }, + ); + } + + List _buildSuggestions(String suggest) { + List suggestions = []; + for (var char in suggest.characters) { + if (query.contains(char)) { + suggestions.add( + TextSpan( + text: char, + style: const TextStyle(color: Colors.blue, fontWeight: FontWeight.bold), + ) + ); + } else { + suggestions.add( + TextSpan( + text: char, + style: const TextStyle(color: Colors.grey), + ) + ); + } + } + return suggestions; + } + + @override + ThemeData appBarTheme(BuildContext context) { + // + return super.appBarTheme(context); + } +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/pages/system/settings/controller.dart b/apps/flutter/dev_app/lib/pages/system/settings/controller.dart index b26160553..5b88bd38b 100644 --- a/apps/flutter/dev_app/lib/pages/system/settings/controller.dart +++ b/apps/flutter/dev_app/lib/pages/system/settings/controller.dart @@ -1,4 +1,5 @@ import 'package:core/services/index.dart'; +import 'package:core/dependency/index.dart'; import 'package:core/utils/string.extensions.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -6,8 +7,8 @@ import 'package:get/get.dart'; import 'state.dart'; class SystemSettingsController extends GetxController { - SessionService get sessionService => Get.find(); - ConfigStateService get configStateService => Get.find(); + SessionService get sessionService => injector.get(); + ConfigStateService get configStateService => injector.get(); final Rx _state = Rx(SettingsState( languages: [], @@ -33,9 +34,8 @@ class SystemSettingsController extends GetxController { } void _initLanguages() { - var localization = configStateService.getLocalization(); _state.update((val) { - val?.languages = localization?.languages; + val?.languages = configStateService.getSupportedLocales(); }); } diff --git a/apps/flutter/dev_app/lib/services/application.initial.flutter.service.dart b/apps/flutter/dev_app/lib/services/application.initial.flutter.service.dart new file mode 100644 index 000000000..2f4692363 --- /dev/null +++ b/apps/flutter/dev_app/lib/services/application.initial.flutter.service.dart @@ -0,0 +1,24 @@ +import 'package:core/models/common.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_app_environment/flutter_app_environment.dart'; + +import 'package:core/services/application.initial.dart'; + +class FlutterApplicationInitialService extends ApplicationInitialService { + @override + Future initialApp() async { + var envType = EnvironmentType.development; + if (kReleaseMode) { + envType = EnvironmentType.production; + } else if (kProfileMode) { + envType = EnvironmentType.test; + } + + await Environment.initFromJson( + environmentType: envType, + fromJson: Application.fromJson, + ); + + return Environment.instance().config; + } +} \ No newline at end of file diff --git a/apps/flutter/core/lib/services/signalr.service.dart b/apps/flutter/dev_app/lib/services/aspnetcore.signalr.service.dart similarity index 90% rename from apps/flutter/core/lib/services/signalr.service.dart rename to apps/flutter/dev_app/lib/services/aspnetcore.signalr.service.dart index 467f9178c..b7b02b0be 100644 --- a/apps/flutter/core/lib/services/signalr.service.dart +++ b/apps/flutter/dev_app/lib/services/aspnetcore.signalr.service.dart @@ -1,22 +1,14 @@ import 'dart:async'; +import 'package:core/abstracts/signalr.service.dart'; +import 'package:core/models/common.dart'; +import 'package:core/services/session.service.dart'; import 'package:core/utils/logging.dart'; import 'package:rxdart/rxdart.dart'; import 'package:signalr_netcore/signalr_client.dart'; -import 'session.service.dart'; - -class SignalrMessage { - SignalrMessage( - this.method, - this.data, - ); - String method; - List data; -} - -class SignalrService { - SignalrService(String url, +class AspNetCoreSignalrService extends SignalrService { + AspNetCoreSignalrService(String url, { bool autoStart = false, bool automaticReconnect = true, @@ -77,32 +69,38 @@ class SignalrService { }); } + @override Future? start() { return _hubConnection.start(); } + @override Future stop() { return _hubConnection.stop(); } + @override StreamSubscription onClose(Function(Exception?) listen, { bool Function(Exception?)? filter}) { return _onClose .where((event) => filter != null ? filter(event) : true) .listen(listen); } + @override StreamSubscription onReconnecting(Function(Exception?) listen, { bool Function(Exception?)? filter}) { return _onReconnecting .where((event) => filter != null ? filter(event) : true) .listen(listen); } + @override StreamSubscription onReconnected(Function(String?) listen, { bool Function(String?)? filter}) { return _onReconnected .where((event) => filter != null ? filter(event) : true) .listen(listen); } + @override Stream subscribe(String methodName) { _hubConnection.on(methodName, (data) { if (data == null) return; @@ -111,14 +109,17 @@ class SignalrService { return _onReceived.where((message) => message.method == methodName); } + @override void unsubscribe(String methodName,) { _hubConnection.off(methodName); } + @override Future send(String methodName, { List? args }) { return _hubConnection.send(methodName, args: args); } + @override Future invoke(String methodName, { List? args }) { return _hubConnection.invoke(methodName, args: args); } diff --git a/apps/flutter/dev_app/lib/services/index.dart b/apps/flutter/dev_app/lib/services/index.dart index 7a3ae50a9..79e575eff 100644 --- a/apps/flutter/dev_app/lib/services/index.dart +++ b/apps/flutter/dev_app/lib/services/index.dart @@ -1 +1,4 @@ -export 'notification.send.local.service.dart'; \ No newline at end of file +export 'application.initial.flutter.service.dart'; +export 'aspnetcore.signalr.service.dart'; +export 'notification.send.local.service.dart'; +export 'translation.service.res.service.dart'; \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/services/notification.send.local.service.dart b/apps/flutter/dev_app/lib/services/notification.send.local.service.dart index 9c1ea36b2..beddf7184 100644 --- a/apps/flutter/dev_app/lib/services/notification.send.local.service.dart +++ b/apps/flutter/dev_app/lib/services/notification.send.local.service.dart @@ -1,23 +1,25 @@ import 'dart:async'; -import 'package:core/config/index.dart'; +import 'package:core/index.dart'; import 'package:get/get.dart'; import 'package:rxdart/rxdart.dart' hide Notification; import 'package:core/models/notifications.dart'; -import 'package:core/services/notification.send.service.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; class FlutterLocalNotificationsSendService extends NotificationSendService { + FlutterLocalNotificationsSendService(super._injector); final RxInt nid = 0.obs; final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); final Subject _notifications$ = BehaviorSubject(); final Subject _selectedNotifications$ = BehaviorSubject(); - final EnvConfig _env = Environment.current; + + EnvironmentService get _environmentService => resolve(); Future initAsync() async { + var environment = _environmentService.getEnvironment(); const initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/logo'); var initializationSettingsLinux = LinuxInitializationSettings( - defaultActionName: _env.notifications?.linux?.defaultActionName ?? 'Open notification', + defaultActionName: environment.notifications?.linux?.defaultActionName ?? 'Open notification', ); var initializationSettingsDarwin = DarwinInitializationSettings( onDidReceiveLocalNotification: (id, title, body, payload) { @@ -54,10 +56,11 @@ class FlutterLocalNotificationsSendService extends NotificationSendService { } NotificationDetails _buildDetails() { + var environment = _environmentService.getEnvironment(); var androidDetails = AndroidNotificationDetails( - _env.notifications?.android?.channelId ?? 'abp-flutter', - _env.notifications?.android?.channelName ?? 'abp-flutter', - channelDescription: _env.notifications?.android?.channelDescription); + environment.notifications?.android?.channelId ?? 'abp-flutter', + environment.notifications?.android?.channelName ?? 'abp-flutter', + channelDescription: environment.notifications?.android?.channelDescription); const darwinDetails = DarwinNotificationDetails(); diff --git a/apps/flutter/dev_app/lib/services/translation.service.res.service.dart b/apps/flutter/dev_app/lib/services/translation.service.res.service.dart new file mode 100644 index 000000000..82a9dfe84 --- /dev/null +++ b/apps/flutter/dev_app/lib/services/translation.service.res.service.dart @@ -0,0 +1,64 @@ +import 'dart:ui'; + +import 'package:core/services/localization.service.dart'; +import 'package:core/services/service.base.dart'; +import 'package:core/services/session.service.dart'; +import 'package:core/services/translation.service.dart'; +import 'package:core/utils/index.dart'; +import 'package:dev_app/models/translation.state.dart'; +import 'package:get/get.dart'; +import 'package:rxdart/rxdart.dart'; +import 'package:flutter/services.dart' show rootBundle; +import 'dart:convert' show jsonDecode; + +class TranslationResService extends ServiceBase implements TranslationService { + TranslationResService(super.injector); + + final InternalStore _store = InternalStore(state: TranslationState()); + + SessionService get _sessionService => resolve(); + LocalizationService get _localizationService => resolve(); + + @override + void onInit() { + super.onInit(); + _initTranslations(); + } + + void _initTranslations() { + var translation$ = _store.sliceState((state) => state); + translation$.listen((state) async { + //Get.clearTranslations(); + if (state.translations.isEmpty) return; + Get.appendTranslations(state.translations); + await Get.updateLocale(Locale.fromSubtags(languageCode: state.language!)); + }); + _store.patch((state) { + state.translations = _localizationService.getResources(); + }); + _sessionService.onLanguageChange$() + .whereNotNull() + .switchMap((language) => Stream.fromFuture(_mapTranslationsMap(language))) + .listen(_store.set); + } + + Future _mapTranslationsMap(String language) async { + Map> translationsMap = {}; + var filePath = 'res/translations/$language.json'; + var content = await rootBundle.loadString(filePath); + var translationsObject = jsonDecode(content) as Map; + translationsMap.putIfAbsent( + language, + () => translationsObject.map((key, value) => MapEntry(key, value)) + ); + return TranslationState( + language: language, + translations: translationsMap, + ); + } + + @override + Map> getResources() { + return _store.state.translations; + } +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/utils/initial.utils.dart b/apps/flutter/dev_app/lib/utils/initial.utils.dart new file mode 100644 index 000000000..14a82251b --- /dev/null +++ b/apps/flutter/dev_app/lib/utils/initial.utils.dart @@ -0,0 +1,72 @@ +import 'package:core/dependency/index.dart'; +import 'package:core/services/index.dart'; +import 'package:core/tokens/index.dart'; +import 'package:core/utils/index.dart'; +import 'package:dev_app/services/notification.send.local.service.dart'; +import 'package:flex_color_scheme/flex_color_scheme.dart'; + +class InitialUtils { + static Future initialState(Injector injector) async { + /// 初始化应用程序 + var applicationInitialService = injector.get(); + var application = await applicationInitialService.initialApp(); + injector.inject(application, tag: AbpTokens.application); + /// 初始化环境配置 + var environmentService = injector.get(); + environmentService.setState(application.environment); + + await EnvironmentUtils.mergeRemoteEnvironment(injector, application.environment); + + /// 放在初始化环境之后 + await injector.injectAsync((injector) async { + var service = FlutterLocalNotificationsSendService(injector); + await service.initAsync(); + return service; + }, permanent: true); + } + + static void initThemeData() { + ThemeUtils.lightTheme = FlexThemeData.light( + scheme: FlexScheme.amber, + surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, + blendLevel: 7, + subThemesData: const FlexSubThemesData( + blendOnLevel: 10, + blendOnColors: false, + useTextTheme: true, + useM2StyleDividerInM3: true, + thinBorderWidth: 0.5, + thickBorderWidth: 0.5, + defaultRadius: 0.0, + cardRadius: 6.0, + ), + visualDensity: FlexColorScheme.comfortablePlatformDensity, + useMaterial3: true, + swapLegacyOnMaterial3: true, + // To use the Playground font, add GoogleFonts package and uncomment + // fontFamily: GoogleFonts.notoSans().fontFamily, + ); + ThemeUtils.darkTheme = FlexThemeData.dark( + scheme: FlexScheme.amber, + surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold, + blendLevel: 13, + subThemesData: const FlexSubThemesData( + blendOnLevel: 20, + useTextTheme: true, + useM2StyleDividerInM3: true, + thinBorderWidth: 0.5, + thickBorderWidth: 0.5, + defaultRadius: 0.0, + cardRadius: 6.0, + ), + visualDensity: FlexColorScheme.comfortablePlatformDensity, + useMaterial3: true, + swapLegacyOnMaterial3: true, + // To use the Playground font, add GoogleFonts package and uncomment + // fontFamily: GoogleFonts.notoSans().fontFamily, + ); + } + + static void initComponent(Injector injector) { + } +} \ No newline at end of file diff --git a/apps/flutter/dev_app/lib/utils/localization.dart b/apps/flutter/dev_app/lib/utils/localization.dart index e3c977e58..0d2c45668 100644 --- a/apps/flutter/dev_app/lib/utils/localization.dart +++ b/apps/flutter/dev_app/lib/utils/localization.dart @@ -1,9 +1,13 @@ -import 'package:core/services/localization.service.dart'; +import 'package:core/dependency/index.dart'; +import 'package:core/services/translation.service.dart'; import 'package:get/get.dart'; class AbpTranslations extends Translations { - AbpTranslations(this.localizationService); - final LocalizationService localizationService; + AbpTranslations(this._injector); + final Injector _injector; + + TranslationService get _translationService => _injector.get(); + @override - Map> get keys => localizationService.getResources(); + Map> get keys => _translationService.getResources(); } \ No newline at end of file diff --git a/apps/flutter/dev_app/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/dev_app/linux/flutter/generated_plugin_registrant.cc index e71a16d23..f6f23bfe9 100644 --- a/apps/flutter/dev_app/linux/flutter/generated_plugin_registrant.cc +++ b/apps/flutter/dev_app/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/apps/flutter/dev_app/linux/flutter/generated_plugins.cmake b/apps/flutter/dev_app/linux/flutter/generated_plugins.cmake index 2e1de87a7..f16b4c342 100644 --- a/apps/flutter/dev_app/linux/flutter/generated_plugins.cmake +++ b/apps/flutter/dev_app/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/apps/flutter/dev_app/pubspec.lock b/apps/flutter/dev_app/pubspec.lock index 8777b5b7d..bb2298370 100644 --- a/apps/flutter/dev_app/pubspec.lock +++ b/apps/flutter/dev_app/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "0816708f5fbcacca324d811297153fe3c8e047beb5c6752e12292d2974c17045" + url: "https://pub.flutter-io.cn" + source: hosted + version: "62.0.0" account: dependency: "direct main" description: @@ -8,6 +16,14 @@ packages: relative: true source: path version: "0.0.1" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "21862995c9932cd082f89d72ae5f5e2c110d1a0204ad06e4ebaee8307b76b834" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.0.0" args: dependency: transitive description: @@ -32,6 +48,54 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.6" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.2.10" built_collection: dependency: transitive description: @@ -40,6 +104,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166" + url: "https://pub.flutter-io.cn" + source: hosted + version: "8.6.1" characters: dependency: transitive description: @@ -48,6 +120,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" clock: dependency: transitive description: @@ -56,6 +136,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.5.0" collection: dependency: transitive description: @@ -71,6 +159,14 @@ packages: relative: true source: path version: "0.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.1" core: dependency: "direct main" description: @@ -102,6 +198,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" + dart_internal: + dependency: transitive + description: + name: dart_internal + sha256: dae3976f383beddcfcd07ad5291a422df2c8c0a8a03c52cda63ac7b4f26e0f4e + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.8" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.2" + date_format: + dependency: "direct main" + description: + name: date_format + sha256: "8e5154ca363411847220c8cbc43afcf69c08e8debe40ba09d57710c25711760c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.7" dbus: dependency: transitive description: @@ -142,6 +262,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" flex_color_scheme: dependency: "direct main" description: @@ -164,7 +292,7 @@ packages: source: sdk version: "0.0.0" flutter_app_environment: - dependency: transitive + dependency: "direct main" description: name: flutter_app_environment sha256: "329cef61e9fa42bdae560d1a86fdf37dd242cd0efff9b2f5f2a7ca1081b6809a" @@ -179,6 +307,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.0.5" + flutter_highlight: + dependency: transitive + description: + name: flutter_highlight + sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.0" flutter_lints: dependency: "direct dev" description: @@ -237,6 +373,19 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.0" get: dependency: "direct main" description: @@ -253,6 +402,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.1" + highlight: + dependency: transitive + description: + name: highlight + sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.0" http: dependency: transitive description: @@ -261,6 +434,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.13.6" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -277,6 +458,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.18.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" js: dependency: transitive description: @@ -286,13 +475,21 @@ packages: source: hosted version: "0.6.7" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.flutter-io.cn" source: hosted version: "4.8.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.7.1" lints: dependency: transitive description: @@ -310,13 +507,29 @@ packages: source: hosted version: "1.4.0" logging: - dependency: "direct dev" + dependency: transitive description: name: logging sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.1.1" + markdown_widget: + dependency: "direct main" + description: + name: markdown_widget + sha256: "088feae6be2dd527c7dd54e06ad104a3e70505aff2ce14a3b464482551a0e273" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0" matcher: dependency: transitive description: @@ -349,6 +562,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" notifications: dependency: "direct main" description: @@ -356,6 +577,29 @@ packages: relative: true source: path version: "0.0.1" + oauth: + dependency: "direct main" + description: + path: "../oauth" + relative: true + source: path + version: "0.0.1" + oauth_dio: + dependency: transitive + description: + name: oauth_dio + sha256: c4592e735270b1aa1ac6f584556d25a41a941a331fac0166c928d4b1b36ea78c + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.7" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -428,6 +672,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" + platforms: + dependency: "direct main" + description: + path: "../platform" + relative: true + source: path + version: "0.0.1" plugin_platform_interface: dependency: transitive description: @@ -436,6 +687,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.1" process: dependency: transitive description: @@ -444,6 +703,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.3" rxdart: dependency: "direct main" description: @@ -460,8 +735,32 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.2.9" + scroll_to_index: + dependency: transitive + description: + name: scroll_to_index + sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" signalr_netcore: - dependency: "direct dev" + dependency: "direct main" description: name: signalr_netcore sha256: "400ced9b03644706fbbc317fd50f4f08c2c0ae4d164082365788f1734b904437" @@ -473,6 +772,22 @@ packages: description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.4" source_span: dependency: transitive description: @@ -505,6 +820,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -537,6 +860,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.9.2" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" tuple: dependency: transitive description: @@ -553,6 +884,70 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.2" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.12" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.0.36" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.6" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.3" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.18" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.7" vector_math: dependency: transitive description: @@ -561,6 +956,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.0+2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" web_socket_channel: dependency: transitive description: @@ -593,6 +1004,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.2" sdks: - dart: ">=3.0.5 <4.0.0" + dart: ">=3.0.5 <3.2.0" flutter: ">=3.10.0" diff --git a/apps/flutter/dev_app/pubspec.yaml b/apps/flutter/dev_app/pubspec.yaml index 44db597b2..7336089e5 100644 --- a/apps/flutter/dev_app/pubspec.yaml +++ b/apps/flutter/dev_app/pubspec.yaml @@ -32,29 +32,43 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter + + # Framework core: path: '../core' components: path: '../components' + oauth: + path: '../oauth' # Modules account: path: '../account' notifications: path: '../notifications' - - dio: - flutter_easyloading: - flutter_picker: - get: - get_storage: - rxdart: - rxdart_ext: + platforms: + path: '../platform' + + dio: ^5.2.0+1 + flutter_easyloading: ^3.0.5 + flutter_picker: ^2.1.0 + get: ^4.6.5 + get_storage: ^2.1.1 + rxdart: ^0.27.7 + rxdart_ext: ^0.2.9 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + json_annotation: ^4.8.1 flex_color_scheme: ^7.1.2 flutter_local_notifications: ^14.1.1 + flutter_app_environment: ^1.0.1 + signalr_netcore: ^1.3.4 + markdown_widget: ^2.2.0 + date_format: ^2.0.7 + +dependency_overrides: + dio: ^5.2.0+1 dev_dependencies: flutter_test: @@ -67,8 +81,8 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^2.0.0 - logging: ^1.0.1 - signalr_netcore: ^1.3.4 + build_runner: ^2.4.5 + json_serializable: ^6.7.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -85,6 +99,7 @@ flutter: assets: - res/config/ - res/images/ + - res/translations/ # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg diff --git a/apps/flutter/dev_app/res/config/demo.json b/apps/flutter/dev_app/res/config/demo.json index 34fdd37b1..49b54960f 100644 --- a/apps/flutter/dev_app/res/config/demo.json +++ b/apps/flutter/dev_app/res/config/demo.json @@ -1,13 +1,43 @@ { - "baseUrl": "http://127.0.0.1:30000", - "clientId": "abp-flutter", - "clientSecret": "1q2w3e*", - "authority": "http://127.0.0.1:30000", - "uploadFilesUrl": "", - "staticFilesUrl": "", - "tenantKey": "__tenant", - "defaultLanguage": "en", + "application": { + "name": "app-flutter" + }, + "auth": { + "clientId": "abp-flutter", + "clientSecret": "1q2w3e*", + "authority": "http://127.0.0.1:30000" + }, + "tenant": { + "tenantKey": "__tenant" + }, + "localization": { + "useLocalResources": true, + "defaultLanguage": "zh-Hans", + "supportedLocales": [ + { + "cultureName": "en", + "displayName": "English" + }, + { + "cultureName": "zh-Hans", + "displayName": "简体中文" + } + ] + }, + "remoteServices": { + "default": { + "url": "http://127.0.0.1:30000" + }, + "avatar": { + "url": "http://127.0.0.1:30000/api/files/static/users/p/" + } + }, + "remoteEnvironment": { + "url": "", + "strategy": "deepmerge" + }, "notifications": { + "serverUrl": "http://127.0.0.1:30000/signalr-hubs/notifications", "android": { "channelId": "abp-flutter", "channelName": "abp-flutter", diff --git a/apps/flutter/dev_app/res/translations/en.json b/apps/flutter/dev_app/res/translations/en.json new file mode 100644 index 000000000..602e12384 --- /dev/null +++ b/apps/flutter/dev_app/res/translations/en.json @@ -0,0 +1,61 @@ +{ + "401Message": "Unauthorized", + "403Message": "Forbidden", + "403MessageDetail": "You are not authorized to perform this operation!", + "404Message": "Page not found", + "404MessageDetail": "Sorry, there's nothing at this address.", + "500Message": "Internal Server Error", + "Center:Feedback": "Feedback", + "Center:Help": "Help", + "Center:Info": "Info", + "Center:Messages": "Messages", + "Center:Settings": "Settings", + "DisplayName:Abp.Localization.DefaultLanguage": "Default language", + "Description:Abp.Localization.DefaultLanguage": "The default language of the application.", + "DefaultErrorMessage": "An error has occurred!", + "DefaultErrorMessageDetail": "Error detail not sent by server.", + "DefaultErrorMessage401": "You are not authenticated!", + "DefaultErrorMessage401Detail": "You should sign in to perform this operation.", + "DefaultErrorMessage403": "You are not authorized!", + "DefaultErrorMessage403Detail": "You are not allowed to perform this operation!", + "DefaultErrorMessage404": "Resource not found!", + "DefaultErrorMessage404Detail": "The resource requested could not found on the server!", + "Label:AccountSettings": "Account Settings", + "Label:Anonymous": "Anonymous", + "Label:CleanCache": "Clean Cache", + "Label:ClickToLogin": "Click to login", + "Label:EnableNotificationSubTitle": "Enable to support global notifications", + "Label:EnableNotificationTitle": "Enable Notification", + "Label:ForgotPassword": "Forgot password?", + "Label:Login": "Login", + "Label:LoginSubTitle": "Log in to continue", + "Label:LoginTitle": "Welcome to login", + "Label:Logout": "Logout", + "Label:NoAccount": "No account?", + "Label:NotificationsSubTitle": "List of supported notification types", + "Label:NotificationsTitle": "Notifications", + "Label:NotifierSettings": "Notifier Settings", + "Label:PasswordRequired": "Please enter password", + "Label:PhoneNumberNotBound": "PhoneNumber Not Bound", + "Label:Submit": "Submit", + "Label:SwitchTheme": "Switch Theme", + "Label:SystemSettings": "System Settings", + "Label:Theme": "Theme", + "Label:UserNameRequired": "Please enter your username", + "Label:Cancel": "Cancel", + "Label:Confirm": "Confirm", + "Label:LoginToPortal": "Login To Portal", + "Languages": "Languages", + "Page:Center": "Center", + "Page:Home": "Home", + "Page:Notification": "Notification", + "Page:Notifications": "Notifications", + "Page:UserInfo": "User Info", + "Page:UserProfile": "User profile", + "Page:Work": "Work", + "Prompt:ApiRequestFailed": "The interface request failed, please try again later!", + "Prompt:SessionTimeout": "Your session has timed out. Please log in again!", + "Theme:Dark": "Dark", + "Theme:Light": "Light", + "Theme:System": "System" +} \ No newline at end of file diff --git a/apps/flutter/dev_app/res/translations/zh-Hans.json b/apps/flutter/dev_app/res/translations/zh-Hans.json new file mode 100644 index 000000000..bf9ae99b8 --- /dev/null +++ b/apps/flutter/dev_app/res/translations/zh-Hans.json @@ -0,0 +1,61 @@ +{ + "401Message": "未授权", + "403Message": "禁止访问", + "403MessageDetail": "您没有权限执行此操作!", + "404Message": "网页未找到", + "404MessageDetail": "抱歉, 这个地址是空的.", + "500Message": "内部服务器错误", + "Center:Feedback": "意见反馈", + "Center:Help": "在线帮助", + "Center:Info": "关于", + "Center:Messages": "我的消息", + "Center:Settings": "设置", + "DisplayName:Abp.Localization.DefaultLanguage": "默认语言", + "Description:Abp.Localization.DefaultLanguage": "应用程序的默认语言.", + "DefaultErrorMessage": "发生错误!", + "DefaultErrorMessageDetail": "服务器未发送错误的详细信息.", + "DefaultErrorMessage401": "未通过身份验证!", + "DefaultErrorMessage401Detail": "你需要进行身份认证(登录)后再执行此操作.", + "DefaultErrorMessage403": "你没有权限!", + "DefaultErrorMessage403Detail": "你不能执行此操作!", + "DefaultErrorMessage404": "未找到资源!", + "DefaultErrorMessage404Detail": "未在服务中找到请求的资源!", + "Label:AccountSettings": "账号设置", + "Label:Anonymous": "游客", + "Label:CleanCache": "清理缓存", + "Label:ClickToLogin": "点击去登录", + "Label:EnableNotificationSubTitle": "启用以支持全局通知", + "Label:EnableNotificationTitle": "启用通知", + "Label:ForgotPassword": "忘记密码?", + "Label:Login": "登录", + "Label:LoginSubTitle": "登录后继续使用", + "Label:LoginTitle": "欢迎回来", + "Label:Logout": "退出登录", + "Label:NoAccount": "没有账号?", + "Label:NotificationsSubTitle": "支持的通知类型列表", + "Label:NotificationsTitle": "通知列表", + "Label:NotifierSettings": "通知设置", + "Label:PasswordRequired": "请输入密码", + "Label:PhoneNumberNotBound": "未绑定手机号", + "Label:Submit": "提交", + "Label:SwitchTheme": "切换主题", + "Label:SystemSettings": "系统设置", + "Label:Theme": "主题", + "Label:UserNameRequired": "请输入用户名", + "Label:Cancel": "取消", + "Label:Confirm": "确认", + "Label:LoginToPortal": "登录到门户", + "Languages": "语言", + "Page:Center": "个人中心", + "Page:Home": "首页", + "Page:Notification": "通知设置", + "Page:Notifications": "通知列表", + "Page:UserInfo": "用户信息", + "Page:UserProfile": "个人信息", + "Page:Work": "工作", + "Prompt:ApiRequestFailed": "请求出错,请稍候重试!", + "Prompt:SessionTimeout": "您的会话已超时, 请重新登录!", + "Theme:Dark": "深色", + "Theme:Light": "浅色", + "Theme:System": "跟随系统" +} \ No newline at end of file diff --git a/apps/flutter/dev_app/translation.json b/apps/flutter/dev_app/translation.json deleted file mode 100644 index de59c063e..000000000 --- a/apps/flutter/dev_app/translation.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "culture": "en", - "texts": { - "Center:Feedback": "Feedback", - "Center:Help": "Help", - "Center:Info": "Info", - "Center:Settings": "Settings", - "Label:AccountSettings": "Account Settings", - "Label:Anonymous": "Anonymous", - "Label:CleanCache": "Clean Cache", - "Label:ClickToLogin": "Click to login", - "Label:EnableNotificationSubTitle": "Enable to support global notifications", - "Label:EnableNotificationTitle": "Enable Notification", - "Label:ForgotPassword": "Forgot password?", - "Label:Login": "Login", - "Label:LoginSubTitle": "Log in to continue", - "Label:LoginTitle": "Welcome to login", - "Label:Logout": "Logout", - "Label:NoAccount": "No account?", - "Label:NotificationsSubTitle": "List of supported notification types", - "Label:NotificationsTitle": "Notifications", - "Label:NotifierSettings": "Notifier Settings", - "Label:PasswordRequired": "Please enter password", - "Label:PhoneNumberNotBound": "PhoneNumber Not Bound", - "Label:Submit": "Submit", - "Label:SwitchTheme": "Switch Theme", - "Label:SystemSettings": "System Settings", - "Label:Theme": "Theme", - "Label:UserNameRequired": "Please enter your username", - "Lable:Cancel": "Cancel", - "Lable:Confirm": "Confirm", - "Lable:LoginToPortal": "Login To Portal", - "Page:Center": "Center", - "Page:Home": "Home", - "Page:Notification": "Notification", - "Page:UserInfo": "User Info", - "Page:UserProfile": "User profile", - "Page:Work": "Work", - "Theme:Dark": "Dark", - "Theme:Light": "Light", - "Theme:System": "System" - } -} \ No newline at end of file diff --git a/apps/flutter/dev_app/translation.zh-Hansjson b/apps/flutter/dev_app/translation.zh-Hansjson deleted file mode 100644 index c104de8aa..000000000 --- a/apps/flutter/dev_app/translation.zh-Hansjson +++ /dev/null @@ -1,43 +0,0 @@ -{ - "culture": "zh-Hans", - "texts": { - "Center:Feedback": "意见反馈", - "Center:Help": "在线帮助", - "Center:Info": "关于", - "Center:Settings": "设置", - "Label:AccountSettings": "账号设置", - "Label:Anonymous": "游客", - "Label:CleanCache": "清理缓存", - "Label:ClickToLogin": "点击去登录", - "Label:EnableNotificationSubTitle": "启用以支持全局通知", - "Label:EnableNotificationTitle": "启用通知", - "Label:ForgotPassword": "忘记密码?", - "Label:Login": "登录", - "Label:LoginSubTitle": "登录后继续使用", - "Label:LoginTitle": "欢迎回来", - "Label:Logout": "退出登录", - "Label:NoAccount": "没有账号?", - "Label:NotificationsSubTitle": "支持的通知类型列表", - "Label:NotificationsTitle": "通知列表", - "Label:NotifierSettings": "通知设置", - "Label:PasswordRequired": "请输入密码", - "Label:PhoneNumberNotBound": "未绑定手机号", - "Label:Submit": "提交", - "Label:SwitchTheme": "切换主题", - "Label:SystemSettings": "系统设置", - "Label:Theme": "主题", - "Label:UserNameRequired": "请输入用户名", - "Lable:Cancel": "取消", - "Lable:Confirm": "确认", - "Lable:LoginToPortal": "登录到门户", - "Page:Center": "个人中心", - "Page:Home": "首页", - "Page:Notification": "通知设置", - "Page:UserInfo": "用户信息", - "Page:UserProfile": "个人信息", - "Page:Work": "工作", - "Theme:Dark": "深色", - "Theme:Light": "浅色", - "Theme:System": "跟随系统" - } -} \ No newline at end of file diff --git a/apps/flutter/dev_app/windows/flutter/generated_plugin_registrant.cc b/apps/flutter/dev_app/windows/flutter/generated_plugin_registrant.cc index 8b6d4680a..4f7884874 100644 --- a/apps/flutter/dev_app/windows/flutter/generated_plugin_registrant.cc +++ b/apps/flutter/dev_app/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/apps/flutter/dev_app/windows/flutter/generated_plugins.cmake b/apps/flutter/dev_app/windows/flutter/generated_plugins.cmake index b93c4c30c..88b22e5c7 100644 --- a/apps/flutter/dev_app/windows/flutter/generated_plugins.cmake +++ b/apps/flutter/dev_app/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/apps/flutter/notifications/.flutter-plugins b/apps/flutter/notifications/.flutter-plugins index 6a0bc2615..9b4283a44 100644 --- a/apps/flutter/notifications/.flutter-plugins +++ b/apps/flutter/notifications/.flutter-plugins @@ -1,6 +1,13 @@ # This is a generated file; do not edit or check into version control. -path_provider=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ -path_provider_android=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ -path_provider_foundation=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.4\\ -path_provider_linux=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ -path_provider_windows=%UserProfile%\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.4\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ +url_launcher=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher-6.1.12\\ +url_launcher_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_android-6.0.36\\ +url_launcher_ios=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_ios-6.1.4\\ +url_launcher_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_linux-3.0.5\\ +url_launcher_macos=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_macos-3.0.6\\ +url_launcher_web=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_web-2.0.18\\ +url_launcher_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\url_launcher_windows-3.0.7\\ diff --git a/apps/flutter/notifications/.flutter-plugins-dependencies b/apps/flutter/notifications/.flutter-plugins-dependencies index daa9f9afc..a76c5289c 100644 --- a/apps/flutter/notifications/.flutter-plugins-dependencies +++ b/apps/flutter/notifications/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-16 10:42:55.797565","version":"3.10.5"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_ios-6.1.4\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_android-6.0.36\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_macos-3.0.6\\\\","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]},{"name":"url_launcher_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_linux-3.0.5\\\\","native_build":true,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]},{"name":"url_launcher_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_windows-3.0.7\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"url_launcher_web","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\url_launcher_web-2.0.18\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2023-07-20 08:38:12.016329","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/notifications/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/flutter/notifications/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java index 7eb0d9f93..5df48af7f 100644 --- a/apps/flutter/notifications/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java +++ b/apps/flutter/notifications/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -2,6 +2,7 @@ import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugins.pathprovider.PathProviderPlugin; +import io.flutter.plugins.urllauncher.UrlLauncherPlugin; /** * Generated file. Do not edit. @@ -12,6 +13,7 @@ public static void registerWith(PluginRegistry registry) { return; } PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin")); + UrlLauncherPlugin.registerWith(registry.registrarFor("io.flutter.plugins.urllauncher.UrlLauncherPlugin")); } private static boolean alreadyRegisteredWith(PluginRegistry registry) { diff --git a/apps/flutter/notifications/android/local.properties b/apps/flutter/notifications/android/local.properties index 60b1ce328..1a3be4ff1 100644 --- a/apps/flutter/notifications/android/local.properties +++ b/apps/flutter/notifications/android/local.properties @@ -1,2 +1,2 @@ -sdk.dir=%UserProfile%\\AppData\\Local\\Android\\sdk +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/notifications/ios/Runner/GeneratedPluginRegistrant.m b/apps/flutter/notifications/ios/Runner/GeneratedPluginRegistrant.m index c0d0cbad8..a794592d2 100644 --- a/apps/flutter/notifications/ios/Runner/GeneratedPluginRegistrant.m +++ b/apps/flutter/notifications/ios/Runner/GeneratedPluginRegistrant.m @@ -12,10 +12,17 @@ @import path_provider_foundation; #endif +#if __has_include() +#import +#else +@import url_launcher_ios; +#endif + @implementation GeneratedPluginRegistrant + (void)registerWithRegistry:(NSObject*)registry { [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]]; + [FLTURLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTURLLauncherPlugin"]]; } @end diff --git a/apps/flutter/notifications/lib/index.dart b/apps/flutter/notifications/lib/index.dart index e69de29bb..2731e7650 100644 --- a/apps/flutter/notifications/lib/index.dart +++ b/apps/flutter/notifications/lib/index.dart @@ -0,0 +1,6 @@ +export 'notifications.module.dart'; +export './models/index.dart'; +export './pages/index.dart'; +export './proxy/index.dart'; +export './services/index.dart'; +export './tokens/index.dart'; \ No newline at end of file diff --git a/apps/flutter/notifications/lib/models/common.dart b/apps/flutter/notifications/lib/models/common.dart index 177c30fa8..130c25bb5 100644 --- a/apps/flutter/notifications/lib/models/common.dart +++ b/apps/flutter/notifications/lib/models/common.dart @@ -10,27 +10,77 @@ class NotificationPaylod { this.id, required this.title, required this.body, + this.type, + this.state, + this.severity, + this.contentType, this.payload, + this.formUser, + this.createTime, + this.description, }); int? id; String title; String body; String? payload; + String? formUser; + String? description; + DateTime? createTime; + NotificationType? type; + NotificationSeverity? severity; + NotificationReadState? state; + NotificationContentType? contentType; - factory NotificationPaylod.fromData(NotificationData data) { + static String _parseProp(NotificationData data, String prop) { + if (!data.extraProperties.containsKey(prop)) return ''; if (data.extraProperties['L'] == true) { - var title = LocalizableStringInfo.fromJson(data.extraProperties['title']); - var message = LocalizableStringInfo.fromJson(data.extraProperties['message']); - return NotificationPaylod( - title: title.name.trFormat(title.values?.map((key, value) => MapEntry(key, value?.toString() ?? '')) ?? {}), - body: message.name.trFormat(message.values?.map((key, value) => MapEntry(key, value?.toString() ?? '')) ?? {}), - payload: jsonEncode(data.extraProperties), - ); + var formatProp = LocalizableStringInfo.fromJson(data.extraProperties[prop]); + return formatProp.name.trFormat(formatProp.values?.map((key, value) => MapEntry(key, value?.toString() ?? '')) ?? {}); + } else { + return data.extraProperties[prop] as String; } + } + + factory NotificationPaylod.fromDto(UserNotificationDto dto) { + var data = dto.data; + var title = _parseProp(data, 'title'); + var message = _parseProp(data, 'message'); + var description = _parseProp(data, 'description'); + return NotificationPaylod( + id: int.tryParse(dto.id), + title: title, + body: message, + description: description, + payload: jsonEncode(data.extraProperties), + formUser: data.extraProperties['formUser'] as String?, + createTime: data.extraProperties['createTime'] != null + ? DateTime.tryParse(data.extraProperties['createTime'] as String) + : null, + type: dto.type, + state: dto.state, + severity: dto.severity, + contentType: dto.contentType, + ); + } + + factory NotificationPaylod.fromNotification(NotificationInfo notification) { + var data = notification.data; + var title = _parseProp(data, 'title'); + var message = _parseProp(data, 'message'); + var description = _parseProp(data, 'description'); return NotificationPaylod( - title: data.extraProperties['title'] as String, - body: data.extraProperties['message'] as String, + id: int.tryParse(notification.id), + title: title, + body: message, + description: description, payload: jsonEncode(data.extraProperties), + formUser: data.extraProperties['formUser'] as String?, + createTime: data.extraProperties['createTime'] != null + ? DateTime.tryParse(data.extraProperties['createTime'] as String) + : null, + type: notification.type, + severity: notification.severity, + contentType: notification.contentType, ); } } \ No newline at end of file diff --git a/apps/flutter/notifications/lib/models/notification.dart b/apps/flutter/notifications/lib/models/notification.dart index 7b0e868dc..498c22e8d 100644 --- a/apps/flutter/notifications/lib/models/notification.dart +++ b/apps/flutter/notifications/lib/models/notification.dart @@ -1,3 +1,4 @@ +import 'package:core/models/abp.dto.dart'; import 'package:json_annotation/json_annotation.dart'; part 'notification.g.dart'; @@ -48,6 +49,14 @@ enum NotificationSeverity { fatal; } +@JsonEnum() +enum NotificationReadState { + @JsonValue(0) + read, + @JsonValue(1) + unRead +} + @JsonSerializable() class NotificationData { NotificationData({ @@ -179,3 +188,50 @@ class SetSubscriptionDto { SetSubscriptionDto(this.name); String name; } + +@JsonSerializable() +class UserNotificationDto { + UserNotificationDto({ + required this.name, + required this.id, + required this.data, + required this.creationTime, + required this.type, + required this.severity, + required this.state, + required this.contentType, + }); + String name; + String id; + NotificationData data; + DateTime creationTime; + NotificationType type; + NotificationSeverity severity; + NotificationReadState state; + NotificationContentType? contentType; + + factory UserNotificationDto.fromJson(Map json) => _$UserNotificationDtoFromJson(json); + Map toJson() => _$UserNotificationDtoToJson(this); +} + +class UserNotificationGetByPagedDto extends PagedAndSortedResultRequestDto { + UserNotificationGetByPagedDto({ + super.sorting, + super.skipCount, + super.maxResultCount, + this.filter, + this.readState, + }); + String? filter; + NotificationReadState? readState; + + @override + Map toJson() => + { + 'sorting': sorting, + 'skipCount': skipCount, + 'maxResultCount': maxResultCount, + 'filter': filter, + 'readState': readState, + }; +} diff --git a/apps/flutter/notifications/lib/models/notification.g.dart b/apps/flutter/notifications/lib/models/notification.g.dart index 44047dff7..0dacda542 100644 --- a/apps/flutter/notifications/lib/models/notification.g.dart +++ b/apps/flutter/notifications/lib/models/notification.g.dart @@ -166,3 +166,35 @@ Map _$UserSubscreNotificationDtoToJson( { 'name': instance.name, }; + +UserNotificationDto _$UserNotificationDtoFromJson(Map json) => + UserNotificationDto( + name: json['name'] as String, + id: json['id'] as String, + data: NotificationData.fromJson(json['data'] as Map), + creationTime: DateTime.parse(json['creationTime'] as String), + type: $enumDecode(_$NotificationTypeEnumMap, json['type']), + severity: $enumDecode(_$NotificationSeverityEnumMap, json['severity']), + state: $enumDecode(_$NotificationReadStateEnumMap, json['state']), + contentType: json['contentType'] == null + ? null + : $enumDecode(_$NotificationContentTypeEnumMap, json['contentType']), + ); + +Map _$UserNotificationDtoToJson( + UserNotificationDto instance) => + { + 'name': instance.name, + 'id': instance.id, + 'data': instance.data, + 'creationTime': instance.creationTime.toIso8601String(), + 'type': _$NotificationTypeEnumMap[instance.type]!, + 'severity': _$NotificationSeverityEnumMap[instance.severity]!, + 'state': _$NotificationReadStateEnumMap[instance.state]!, + 'contentType': _$NotificationContentTypeEnumMap[instance.contentType], + }; + +const _$NotificationReadStateEnumMap = { + NotificationReadState.read: 0, + NotificationReadState.unRead: 1, +}; diff --git a/apps/flutter/notifications/lib/models/notification.state.dart b/apps/flutter/notifications/lib/models/notification.state.dart index e2f88e0dd..2b7882188 100644 --- a/apps/flutter/notifications/lib/models/notification.state.dart +++ b/apps/flutter/notifications/lib/models/notification.state.dart @@ -61,10 +61,12 @@ class Notification { required this.lifetime, required this.type, required this.contentType, + this.loading = false, }); String name; String groupName; String displayName; + bool loading; bool isSubscribed; String? description; NotificationLifetime lifetime; diff --git a/apps/flutter/notifications/lib/notifications.module.dart b/apps/flutter/notifications/lib/notifications.module.dart index 4c26a2046..255c43b1e 100644 --- a/apps/flutter/notifications/lib/notifications.module.dart +++ b/apps/flutter/notifications/lib/notifications.module.dart @@ -1,5 +1,6 @@ import 'package:core/modularity/index.dart'; import 'package:get/get.dart'; +import 'package:notifications/proxy/index.dart'; import 'package:notifications/services/index.dart'; import './pages/route.notification.dart'; @@ -11,7 +12,8 @@ class NotificationsModule extends Module { @override void configureServices() { inject(this); - lazyInject(() => NotificationService(), fenix: true); - lazyInject(() => NotificationStateService(), fenix: true); + lazyInject((injector) => NotificationService(injector)); + lazyInject((injector) => MyNotificationAppService(injector)); + lazyInject((injector) => NotificationStateService(injector)); } } \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/index.dart b/apps/flutter/notifications/lib/pages/index.dart index bc1161bbf..519630727 100644 --- a/apps/flutter/notifications/lib/pages/index.dart +++ b/apps/flutter/notifications/lib/pages/index.dart @@ -1 +1,2 @@ -export './notifier/index.dart'; \ No newline at end of file +export './notifier/index.dart'; +export './notifier-list/index.dart'; \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier-list/binding.dart b/apps/flutter/notifications/lib/pages/notifier-list/binding.dart new file mode 100644 index 000000000..906b78b4c --- /dev/null +++ b/apps/flutter/notifications/lib/pages/notifier-list/binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import 'controller.dart'; + +class NotificationsBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => NotificationsController()); + } +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier-list/controller.dart b/apps/flutter/notifications/lib/pages/notifier-list/controller.dart new file mode 100644 index 000000000..0c422fc57 --- /dev/null +++ b/apps/flutter/notifications/lib/pages/notifier-list/controller.dart @@ -0,0 +1,84 @@ +import 'dart:async'; + +import 'package:core/models/abp.dto.dart'; +import 'package:core/dependency/index.dart'; +import 'package:core/services/subscription.service.dart'; +import 'package:get/get.dart'; +import 'package:notifications/models/index.dart'; +import 'package:notifications/proxy/index.dart'; + +import 'state.dart'; + +class NotificationsController extends GetxController with ScrollMixin { + final Rx _state = Rx(NotificationsState()); + NotificationsState get state => _state.value; + + MyNotificationAppService get _myNotificationAppService => injector.get(); + SubscriptionService get _subscriptionService => injector.get(); + + Future refreshState() async { + var dto = await _myNotificationAppService.getList(UserNotificationGetByPagedDto( + skipCount: state.skipCount, + maxResultCount: state.maxResultCount, + )); + updateState(dto); + } + + void showPayload(NotificationPaylod payload) { + if (payload.state == NotificationReadState.unRead) { + //_myNotificationAppService. + } + } + + Future?> fetch() { + return _myNotificationAppService.getList( + UserNotificationGetByPagedDto( + skipCount: state.skipCount, + maxResultCount: state.maxResultCount, + ), + ); + } + + void updateState(PagedResultDto? dto) { + _state.update((val) { + val!.hasMore = dto?.items.length == val.maxResultCount; + if (val.skipCount == 0) { + val.notifications = dto?.items ?? []; + } else { + val.notifications.addAll(dto?.items ?? []); + } + }); + } + + @override + void onInit() { + super.onInit(); + refreshState(); + } + + @override + void onClose() { + _subscriptionService.closeAll(); + super.onClose(); + } + + @override + Future onEndScroll() async { + if (state.hasMore) { + _state.update((val) { + // 防止多次触发 + val!.hasMore = false; + val.skipCount = val.skipCount + val.maxResultCount; + }); + await refreshState(); + } + } + + @override + Future onTopScroll() async { + _state.update((val) { + val!.skipCount = 0; + }); + await refreshState(); + } +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier-list/index.dart b/apps/flutter/notifications/lib/pages/notifier-list/index.dart new file mode 100644 index 000000000..95fc61b96 --- /dev/null +++ b/apps/flutter/notifications/lib/pages/notifier-list/index.dart @@ -0,0 +1,2 @@ +export 'binding.dart'; +export 'view.dart'; \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier-list/state.dart b/apps/flutter/notifications/lib/pages/notifier-list/state.dart new file mode 100644 index 000000000..739139a57 --- /dev/null +++ b/apps/flutter/notifications/lib/pages/notifier-list/state.dart @@ -0,0 +1,14 @@ +import 'package:notifications/models/index.dart'; + +class NotificationsState { + NotificationsState({ + this.notifications = const [], + this.hasMore = true, + this.skipCount = 0, + this.maxResultCount = 10, + }); + bool hasMore; + int skipCount; + int maxResultCount; + List notifications; +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier-list/view.dart b/apps/flutter/notifications/lib/pages/notifier-list/view.dart new file mode 100644 index 000000000..ae5d03afb --- /dev/null +++ b/apps/flutter/notifications/lib/pages/notifier-list/view.dart @@ -0,0 +1,102 @@ +import 'package:components/index.dart'; +import 'package:core/utils/date.format.utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:notifications/models/index.dart'; +import 'controller.dart'; + +class NotificationsPage extends BasePage { + const NotificationsPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Page:Notifications'.tr), + ), + body: SafeArea( + child: RefreshIndicator( + onRefresh: bloc.onTopScroll, + child: Stack( + children: [ + Obx(() => _buildNotifications()), + BackToTop(controller: bloc.scroll), + ], + ), + ), + ), + ); + } + + Widget _buildNotifications() { + return ListView.builder( + itemCount: bloc.state.hasMore + ? bloc.state.notifications.length + 1 + : bloc.state.notifications.length, + itemBuilder: (context, index) { + if (index == bloc.state.notifications.length) { + return Empty.none; + } + var notification = bloc.state.notifications[index]; + var payload = NotificationPaylod.fromDto(notification); + return InkWell( + onTap: () => bloc.showPayload(payload), + child: Container( + padding: const EdgeInsets.only(bottom: 10, left: 10, right: 10), + child: Column( + children: [ + Center( + child: Text(notification.creationTime + .format(['yyyy', '-', 'mm', '-', 'dd', ' ', 'HH', ':', 'nn', ':', 'ss'])), + ), + Card( + child: Column( + children: [ + ListTile( + title: Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Text(payload.title), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('通知来源: ${payload.formUser ?? ''}', textAlign: TextAlign.left,), + Text('通知类型: ${payload.title}', textAlign: TextAlign.left,), + Text('发布时间: ${notification.creationTime + .format(['yyyy', '-', 'mm', '-', 'dd', ' ', 'HH', ':', 'nn', ':', 'ss'])}', + textAlign: TextAlign.left + ), + ], + ), + ), + const Divider(), + const SizedBox( + height: 26, + child: Stack( + children: [ + Positioned( + left: 10, + child: Center(child: Text('查看详情')), + ), + Positioned( + right: 10, + child: Center(child: Icon(Icons.arrow_forward_ios, + size: 13, + color: Colors.grey, + )), + ), + ], + ), + ) + ], + ) + ), + ], + ), + ), + ); + }, + controller: bloc.scroll, + ); + } +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier/controller.dart b/apps/flutter/notifications/lib/pages/notifier/controller.dart index aa14313d5..2b3b29c7e 100644 --- a/apps/flutter/notifications/lib/pages/notifier/controller.dart +++ b/apps/flutter/notifications/lib/pages/notifier/controller.dart @@ -1,19 +1,25 @@ +import 'package:core/dependency/index.dart'; import 'package:get/get.dart'; +import 'package:core/models/request.dart'; +import 'package:core/services/subscription.service.dart'; +import 'package:notifications/proxy/index.dart'; import '../../models/index.dart'; import '../../services/index.dart'; class NotifierManageController extends GetxController { - NotificationStateService get stateService => Get.find(); + NotificationService get _notificationService => injector.get(); + NotificationStateService get _stateService => injector.get(); + SubscriptionService get _subscriptionService => injector.get(); final Rx _state = Rx(NotificationState( isEnabled: true, groups: [])); NotificationState get state => _state.value; - void _updateState() async { - _state.value = stateService.state; - stateService.getNotificationState$() + void _updateState() { + _state.value = _stateService.state; + _stateService.getNotificationState$() .listen((state$) { _state.update((val) { val = state$; @@ -21,12 +27,37 @@ class NotifierManageController extends GetxController { }); } - void onSubscribed(Notification notification, bool isSubscribe) async { - await stateService.subscribe(notification, isSubscribe); + void onSubscribed(Notification notification, bool isSubscribe) { + _stateService.changeLoadingState(notification, true); + var requestOptions = RequestOptions(); + Stream subscribe$; + if (isSubscribe) { + subscribe$ = _notificationService + .subscribe(notification.name, requestOptions: requestOptions) + .asStream(); + } else { + subscribe$ = _notificationService + .unSubscribe(notification.name, requestOptions: requestOptions) + .asStream(); + } + _subscriptionService.subscribeOnce(subscribe$, + done: () { + _stateService.changeSubscribedState(notification, isSubscribe); + _stateService.changeLoadingState(notification, false); + }, + cancel: () { + if (super.isClosed) { + // 页面退出时需要取消网络请求 + requestOptions.cancel(); + // 页面退出时需要改变加载状态 + _stateService.changeLoadingState(notification, false); + } + }, + ); } void onNotificationEnabled(bool isEnabled) { - stateService.subscribeAll(isEnabled); + _stateService.subscribeAll(isEnabled); } @override @@ -34,4 +65,10 @@ class NotifierManageController extends GetxController { super.onInit(); _updateState(); } + + @override + void onClose() { + _subscriptionService.closeAll(); + super.onClose(); + } } \ No newline at end of file diff --git a/apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart b/apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart index 16f860eab..8237a9d0d 100644 --- a/apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart +++ b/apps/flutter/notifications/lib/pages/notifier/widget/notifier_card.dart @@ -44,11 +44,11 @@ class NotifierCard extends StatelessWidget { title: Text(item.displayName), subtitle: Text(item.description ?? ''), value: item.isSubscribed, - onChanged: (checked) { + onChanged: item.loading == false ? (checked) { if (onChange != null) { onChange!(item, checked); } - }, + } : null, )); } return children; diff --git a/apps/flutter/notifications/lib/pages/route.notification.dart b/apps/flutter/notifications/lib/pages/route.notification.dart index 415281e50..3adcd631a 100644 --- a/apps/flutter/notifications/lib/pages/route.notification.dart +++ b/apps/flutter/notifications/lib/pages/route.notification.dart @@ -10,5 +10,10 @@ class NotificationRoute { page: () => const NotifierManagePage(), binding: NotifierManageBinding(), ), + GetPage( + name: NotificationRoutes.notifies, + page: () => const NotificationsPage(), + binding: NotificationsBinding(), + ), ]; } \ No newline at end of file diff --git a/apps/flutter/notifications/lib/proxy/index.dart b/apps/flutter/notifications/lib/proxy/index.dart new file mode 100644 index 000000000..9b72008b3 --- /dev/null +++ b/apps/flutter/notifications/lib/proxy/index.dart @@ -0,0 +1,2 @@ +export 'notification.service.dart'; +export 'my.notification.service.dart'; \ No newline at end of file diff --git a/apps/flutter/notifications/lib/proxy/my.notification.service.dart b/apps/flutter/notifications/lib/proxy/my.notification.service.dart new file mode 100644 index 000000000..485cd6c40 --- /dev/null +++ b/apps/flutter/notifications/lib/proxy/my.notification.service.dart @@ -0,0 +1,23 @@ +import 'package:core/models/index.dart'; +import 'package:core/services/rest.service.dart'; +import 'package:core/services/service.base.dart'; +import 'package:notifications/models/index.dart'; + +class MyNotificationAppService extends ServiceBase { + MyNotificationAppService(super._injector); + + RestService get _restService => resolve(); + + Future> getList([UserNotificationGetByPagedDto? dto]) { + return _restService.request( + method: HttpMethod.GET, + url: '/api/notifications/my-notifilers', + transformer: (res) { + return PagedResultDto.fromJson( + res.data!, + fromJsonT: (json) => UserNotificationDto.fromJson(json as Map),); + }, + queryParameters: dto?.toJson(), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/proxy/notification.service.dart b/apps/flutter/notifications/lib/proxy/notification.service.dart new file mode 100644 index 000000000..2f8d1a691 --- /dev/null +++ b/apps/flutter/notifications/lib/proxy/notification.service.dart @@ -0,0 +1,74 @@ +import 'package:core/models/abp.dto.dart'; +import 'package:core/models/request.dart'; +import 'package:core/services/rest.service.dart'; +import 'package:core/services/service.base.dart'; + +import '../models/notification.dart'; + +class NotificationService extends ServiceBase { + NotificationService(super._injector); + + RestService get _restService => resolve(); + + Future sendAsyncByInput(NotificationSendDto input, { RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.POST, + url: '/api/notifications', + data: input, + requestOptions: requestOptions, + ); + } + + Future subscribe(String name, { RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.POST, + url: '/api/notifications/my-subscribes', + data: { + 'name': name, + }, + requestOptions: requestOptions, + ); + } + + Future unSubscribe(String name, { RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.DELETE, + url: '/api/notifications/my-subscribes?name=$name', + requestOptions: requestOptions, + ); + } + + Future> getMySubscribedListAsync({ RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.GET, + requestOptions: requestOptions, + url: '/api/notifications/my-subscribes/all', + transformer: (res) => ListResultDto( + items: (res.data['items'] as List).map((e) => UserSubscreNotificationDto.fromJson(e)).toList(), + ), + ); + } + + Future> getAssignableNotifiersAsync({ RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.GET, + requestOptions: requestOptions, + url: '/api/notifications/assignables', + transformer: (res) => ListResultDto( + items: (res.data['items'] as List).map((e) => NotificationGroupDto.fromJson(e)).toList(), + ), + ); + } + + Future> getAssignableTemplatesAsync({ RequestOptions? requestOptions }) { + return _restService.request( + method: HttpMethod.GET, + requestOptions: requestOptions, + url: '/api/notifications/assignable-templates', + transformer: (res) => ListResultDto( + items: (res.data['items'] as List) + .map((e) => NotificationTemplateDto.fromJson(e)).toList() + ), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/services/index.dart b/apps/flutter/notifications/lib/services/index.dart index a562143c2..d01d5a9ce 100644 --- a/apps/flutter/notifications/lib/services/index.dart +++ b/apps/flutter/notifications/lib/services/index.dart @@ -1,2 +1 @@ -export 'notification.service.dart'; export 'notification.state.service.dart'; \ No newline at end of file diff --git a/apps/flutter/notifications/lib/services/notification.service.dart b/apps/flutter/notifications/lib/services/notification.service.dart deleted file mode 100644 index 6b913023e..000000000 --- a/apps/flutter/notifications/lib/services/notification.service.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:core/models/abp.dto.dart'; -import 'package:core/services/rest.service.dart'; -import 'package:core/services/service.base.dart'; - -import '../models/notification.dart'; - -class NotificationService extends ServiceBase { - RestService get _restService => find(); - - Future sendAsyncByInput(NotificationSendDto input) { - return _restService.post('/api/notifications', - data: input, - ); - } - - Future subscribe(String name) { - return _restService.post('/api/notifications/my-subscribes', - data: { - 'name': name, - }, - ); - } - - Future unSubscribe(String name) { - return _restService.delete('/api/notifications/my-subscribes?name=$name'); - } - - Future> getMySubscribedListAsync() { - return _restService.get('/api/notifications/my-subscribes/all', - ).then((res) { - return ListResultDto( - items: (res.data['items'] as List).map((e) => UserSubscreNotificationDto.fromJson(e)).toList(), - ); - }); - } - - Future> getAssignableNotifiersAsync() { - return _restService.get('/api/notifications/assignables', - ).then((res) { - return ListResultDto( - items: (res.data['items'] as List).map((e) => NotificationGroupDto.fromJson(e)).toList(), - ); - }); - } - - Future> getAssignableTemplatesAsync() { - return _restService.get('/api/notifications/assignable-templates', - ).then((res) => ListResultDto( - items: (res.data['items'] as List) - .map((e) => NotificationTemplateDto.fromJson(e)).toList() - ), - ); - } -} \ No newline at end of file diff --git a/apps/flutter/notifications/lib/services/notification.state.service.dart b/apps/flutter/notifications/lib/services/notification.state.service.dart index 29c8997a4..037a588d5 100644 --- a/apps/flutter/notifications/lib/services/notification.state.service.dart +++ b/apps/flutter/notifications/lib/services/notification.state.service.dart @@ -1,21 +1,24 @@ import 'dart:convert'; - +import 'package:rxdart/rxdart.dart' hide Notification; +import 'package:notifications/models/notification.dart'; import 'package:core/services/session.service.dart'; import 'package:core/services/service.base.dart'; -import 'package:core/services/signalr.service.dart'; +import 'package:core/abstracts/signalr.service.dart'; import 'package:core/services/storage.service.dart'; import 'package:core/utils/internal.store.dart'; import 'package:notifications/models/notification.state.dart'; import '../tokens/notifications.token.dart'; -import 'notification.service.dart'; +import '../proxy/notification.service.dart'; class NotificationStateService extends ServiceBase { + NotificationStateService(super._injector); + static const String configKey = '_abp_notification_'; - SessionService get _sessionService => find(); - NotificationService get _notificationService => find(); - StorageService get _storageService => find(); - SignalrService get _signalrService => find(tag: NotificationTokens.producer); + SessionService get _sessionService => resolve(); + StorageService get _storageService => resolve(); + NotificationService get _notificationService => resolve(); + SignalrService get _signalrService => resolve(tag: NotificationTokens.producer); final InternalStore _store = InternalStore( state: _initState() @@ -46,21 +49,17 @@ class NotificationStateService extends ServiceBase { return _store.state.findNotification(name); } - Future subscribe(Notification notification, bool isSubscribe) async { - if (isSubscribe) { - await _notificationService.subscribe(notification.name); - } else { - await _notificationService.unSubscribe(notification.name); - } - _changeSubscribedState(notification, isSubscribe); - } - @override void onInit() { super.onInit(); - _sessionService.getProfile$() + _sessionService.onLanguageChange$() + .switchMap((value) => _sessionService.getProfile$()) .listen((profile) async { - if (_sessionService.isAuthenticated) { + if (profile == null) { + _store.patch((state) { + state.groups = []; + }); + } else { await _refreshState(); } }); @@ -76,49 +75,64 @@ class NotificationStateService extends ServiceBase { return configState ?? NotificationState(isEnabled: true, groups: []); } - Future _refreshState() async { - var notifiers = await _notificationService.getAssignableNotifiersAsync(); - var subscres = await _notificationService.getMySubscribedListAsync(); - List groups = []; - - for (var notifierGroup in notifiers.items) { - if (notifierGroup.notifications == null && notifierGroup.notifications?.isEmpty == true) { - continue; - } - - List notifications = []; - for (var notifier in notifierGroup.notifications!) { - notifications.add(Notification( - name: notifier.name, - groupName: notifierGroup.name, - displayName: notifier.displayName ?? notifier.name, - description: notifier.description, - type: notifier.type, - contentType: notifier.contentType, - lifetime: notifier.lifetime, - isSubscribed: subscres.items.any((item) => item.name == notifier.name), - )); - } - - groups.add(NotificationGroup( - name: notifierGroup.name, - displayName: notifierGroup.displayName ?? notifierGroup.name, - notifications: notifications, - )); - } + Future> getGroupAndCombineWithNotification(List groupItems) { + return _notificationService.getMySubscribedListAsync() + .then((subscres) { + List groups = []; + for (var notifierGroup in groupItems) { + if (notifierGroup.notifications == null && notifierGroup.notifications?.isEmpty == true) { + continue; + } + + List notifications = []; + for (var notifier in notifierGroup.notifications!) { + notifications.add(Notification( + name: notifier.name, + groupName: notifierGroup.name, + displayName: notifier.displayName ?? notifier.name, + description: notifier.description, + type: notifier.type, + contentType: notifier.contentType, + lifetime: notifier.lifetime, + isSubscribed: subscres.items.any((item) => item.name == notifier.name), + )); + } + + groups.add(NotificationGroup( + name: notifierGroup.name, + displayName: notifierGroup.displayName ?? notifierGroup.name, + notifications: notifications, + )); + } + return groups; + }); + } + Future _refreshState() async { + var dto = await _notificationService.getAssignableNotifiersAsync(); + var groups = await getGroupAndCombineWithNotification(dto.items); _store.patch((state) { state.groups = groups; }); } - void _changeSubscribedState(Notification notification, bool isSubscribe) { + void changeSubscribedState(Notification notification, bool isSubscribe) { + _store.patch((val) { + var group = val.findGroup(notification.groupName); + if (group == null) return; + var findNotification = group.find(notification.name); + if (findNotification == null) return; + findNotification.isSubscribed = isSubscribe; + }); + } + + void changeLoadingState(Notification notification, bool loading) { _store.patch((val) { var group = val.findGroup(notification.groupName); if (group == null) return; var findNotification = group.find(notification.name); if (findNotification == null) return; - findNotification.isSubscribed = true; + findNotification.loading = loading; }); } } \ No newline at end of file diff --git a/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux b/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux new file mode 120000 index 000000000..d5e0be9c6 --- /dev/null +++ b/apps/flutter/notifications/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/url_launcher_linux-3.0.5/ \ No newline at end of file diff --git a/apps/flutter/notifications/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/notifications/linux/flutter/generated_plugin_registrant.cc index e71a16d23..f6f23bfe9 100644 --- a/apps/flutter/notifications/linux/flutter/generated_plugin_registrant.cc +++ b/apps/flutter/notifications/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/apps/flutter/notifications/linux/flutter/generated_plugins.cmake b/apps/flutter/notifications/linux/flutter/generated_plugins.cmake index 2e1de87a7..f16b4c342 100644 --- a/apps/flutter/notifications/linux/flutter/generated_plugins.cmake +++ b/apps/flutter/notifications/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/apps/flutter/notifications/pubspec.yaml b/apps/flutter/notifications/pubspec.yaml index e43afb750..44dcb000a 100644 --- a/apps/flutter/notifications/pubspec.yaml +++ b/apps/flutter/notifications/pubspec.yaml @@ -15,8 +15,10 @@ dependencies: path: '../core' components: path: '../components' - get: + get: ^4.6.5 + rxdart: ^0.27.7 json_annotation: ^4.8.1 + markdown_widget: ^2.2.0 dev_dependencies: flutter_test: diff --git a/apps/flutter/oauth/.flutter-plugins b/apps/flutter/oauth/.flutter-plugins new file mode 100644 index 000000000..22453877b --- /dev/null +++ b/apps/flutter/oauth/.flutter-plugins @@ -0,0 +1,6 @@ +# This is a generated file; do not edit or check into version control. +path_provider=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.15\\ +path_provider_android=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_android-2.0.27\\ +path_provider_foundation=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_foundation-2.2.4\\ +path_provider_linux=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.11\\ +path_provider_windows=C:\\Users\\eddlevol\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_windows-2.1.7\\ diff --git a/apps/flutter/oauth/.flutter-plugins-dependencies b/apps/flutter/oauth/.flutter-plugins-dependencies new file mode 100644 index 000000000..374a67012 --- /dev/null +++ b/apps/flutter/oauth/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_android-2.0.27\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_foundation-2.2.4\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_linux-2.1.11\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\eddlevol\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.flutter-io.cn\\\\path_provider_windows-2.1.7\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-07-19 17:25:01.623054","version":"3.10.5"} \ No newline at end of file diff --git a/apps/flutter/oauth/.gitignore b/apps/flutter/oauth/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/apps/flutter/oauth/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/apps/flutter/oauth/.metadata b/apps/flutter/oauth/.metadata new file mode 100644 index 000000000..9596faeed --- /dev/null +++ b/apps/flutter/oauth/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: package diff --git a/apps/flutter/oauth/CHANGELOG.md b/apps/flutter/oauth/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/apps/flutter/oauth/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/apps/flutter/oauth/LICENSE b/apps/flutter/oauth/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/apps/flutter/oauth/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/apps/flutter/oauth/README.md b/apps/flutter/oauth/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/apps/flutter/oauth/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/apps/flutter/oauth/analysis_options.yaml b/apps/flutter/oauth/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/apps/flutter/oauth/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/apps/flutter/oauth/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/flutter/oauth/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java new file mode 100644 index 000000000..7eb0d9f93 --- /dev/null +++ b/apps/flutter/oauth/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -0,0 +1,25 @@ +package io.flutter.plugins; + +import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugins.pathprovider.PathProviderPlugin; + +/** + * Generated file. Do not edit. + */ +public final class GeneratedPluginRegistrant { + public static void registerWith(PluginRegistry registry) { + if (alreadyRegisteredWith(registry)) { + return; + } + PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin")); + } + + private static boolean alreadyRegisteredWith(PluginRegistry registry) { + final String key = GeneratedPluginRegistrant.class.getCanonicalName(); + if (registry.hasPlugin(key)) { + return true; + } + registry.registrarFor(key); + return false; + } +} diff --git a/apps/flutter/oauth/android/local.properties b/apps/flutter/oauth/android/local.properties new file mode 100644 index 000000000..1a3be4ff1 --- /dev/null +++ b/apps/flutter/oauth/android/local.properties @@ -0,0 +1,2 @@ +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk +flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/oauth/ios/Flutter/Generated.xcconfig b/apps/flutter/oauth/ios/Flutter/Generated.xcconfig new file mode 100644 index 000000000..80239df7b --- /dev/null +++ b/apps/flutter/oauth/ios/Flutter/Generated.xcconfig @@ -0,0 +1,14 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\oauth +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib\main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 +EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/oauth/ios/Flutter/flutter_export_environment.sh b/apps/flutter/oauth/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 000000000..50b61a78e --- /dev/null +++ b/apps/flutter/oauth/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\oauth" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.h b/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.h new file mode 100644 index 000000000..7a8909271 --- /dev/null +++ b/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.h @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GeneratedPluginRegistrant_h +#define GeneratedPluginRegistrant_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GeneratedPluginRegistrant : NSObject ++ (void)registerWithRegistry:(NSObject*)registry; +@end + +NS_ASSUME_NONNULL_END +#endif /* GeneratedPluginRegistrant_h */ diff --git a/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.m b/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.m new file mode 100644 index 000000000..c0d0cbad8 --- /dev/null +++ b/apps/flutter/oauth/ios/Runner/GeneratedPluginRegistrant.m @@ -0,0 +1,21 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#import "GeneratedPluginRegistrant.h" + +#if __has_include() +#import +#else +@import path_provider_foundation; +#endif + +@implementation GeneratedPluginRegistrant + ++ (void)registerWithRegistry:(NSObject*)registry { + [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]]; +} + +@end diff --git a/apps/flutter/oauth/lib/index.dart b/apps/flutter/oauth/lib/index.dart new file mode 100644 index 000000000..b63ddd01c --- /dev/null +++ b/apps/flutter/oauth/lib/index.dart @@ -0,0 +1,4 @@ +export 'oauth.module.dart'; +export './models/index.dart'; +export './services/index.dart'; +export './utils/index.dart'; \ No newline at end of file diff --git a/apps/flutter/oauth/lib/models/index.dart b/apps/flutter/oauth/lib/models/index.dart new file mode 100644 index 000000000..def8d634f --- /dev/null +++ b/apps/flutter/oauth/lib/models/index.dart @@ -0,0 +1,2 @@ +export 'sms.grant.dart'; +export 'portal.grant.dart'; \ No newline at end of file diff --git a/apps/flutter/oauth/lib/models/portal.grant.dart b/apps/flutter/oauth/lib/models/portal.grant.dart new file mode 100644 index 000000000..1b2da76d5 --- /dev/null +++ b/apps/flutter/oauth/lib/models/portal.grant.dart @@ -0,0 +1,32 @@ + +import 'package:core/index.dart'; +import 'package:dio/dio.dart'; +import 'package:oauth_dio/oauth_dio.dart'; + +class PortalPasswordGrant extends PasswordGrant { + PortalPasswordGrant({ + super.username, + super.password, + super.scope, + this.enterpriseId, + }); + final String? enterpriseId; + + /// Prepare Request + @override + RequestOptions handle(RequestOptions request) { + request.data = { + "grant_type": "portal", + "username": username, + "password": password, + "scope": scope.join(' '), + "enterpriseId": enterpriseId, + }; + if (enterpriseId.isNullOrWhiteSpace()) { + request.extra = { + HttpTokens.ignoreError: 'true', + }; + } + return request; + } +} \ No newline at end of file diff --git a/apps/flutter/oauth/lib/models/sms.grant.dart b/apps/flutter/oauth/lib/models/sms.grant.dart new file mode 100644 index 000000000..c4a0ec368 --- /dev/null +++ b/apps/flutter/oauth/lib/models/sms.grant.dart @@ -0,0 +1,24 @@ +import 'package:dio/dio.dart'; +import 'package:oauth_dio/oauth_dio.dart'; + +class SmsGrant extends OAuthGrantType { + SmsGrant({ + required this.phoneNumber, + required this.code, + this.scope = const [], + }); + final String phoneNumber; + final String code; + final List scope; + + @override + RequestOptions handle(RequestOptions request) { + request.data = { + "grant_type": "phone_verify", + "scope": scope.join(' '), + "phoneNumber": phoneNumber, + "code": code, + }; + return request; + } +} \ No newline at end of file diff --git a/apps/flutter/oauth/lib/oauth.module.dart b/apps/flutter/oauth/lib/oauth.module.dart new file mode 100644 index 000000000..e4b298d38 --- /dev/null +++ b/apps/flutter/oauth/lib/oauth.module.dart @@ -0,0 +1,12 @@ +import 'package:core/modularity/index.dart'; +import 'package:core/services/auth.service.dart'; +import 'package:oauth/services/index.dart'; +import 'package:oauth_dio/oauth_dio.dart'; + +class OAuthModule extends Module { + @override + void configureServices() { + lazyInject((injector) => OAuthService(injector)); + lazyInject((injector) => OAuthStorageService(injector)); + } +} \ No newline at end of file diff --git a/apps/flutter/oauth/lib/services/auth.service.oauth.dart b/apps/flutter/oauth/lib/services/auth.service.oauth.dart new file mode 100644 index 000000000..5cbae0950 --- /dev/null +++ b/apps/flutter/oauth/lib/services/auth.service.oauth.dart @@ -0,0 +1,150 @@ +import 'dart:convert'; + +import 'package:core/dependency/index.dart'; +import 'package:core/models/index.dart'; +import 'package:dio/dio.dart'; +import 'package:oauth/models/index.dart'; +import 'package:oauth_dio/oauth_dio.dart' as authlib; +import 'package:core/services/auth.service.dart'; +import 'package:core/services/environment.service.dart'; +import 'package:core/services/rest.service.dart'; + +class OAuth extends authlib.OAuth { + OAuth({ + required super.tokenUrl, + required super.clientId, + required super.clientSecret, + super.dio, + super.storage, + super.extractor, + super.validator, + }); + + @override + Future requestToken(authlib.OAuthGrantType grantType) { + final request = grantType.handle( + RequestOptions( + method: 'POST', + path: '/', + contentType: 'application/x-www-form-urlencoded', + headers: { + "Authorization": + "Basic ${authlib.stringToBase64.encode('${super.clientId}:${super.clientSecret}')}" + }, + ), + ); + + return super + .dio + .request(super.tokenUrl, + data: request.data, + options: Options( + contentType: request.contentType, + headers: request.headers, + method: request.method, + extra: request.extra, + )) + .then((res) => super.extractor(res)); + } +} + +class OAuthService extends AuthService { + OAuthService(Injector injector) : super(injector){ + _environmentService = injector.get(); + var environment = _environmentService.getEnvironment(); + _auth = OAuth( + tokenUrl: '${environment.auth.getAuthority()}connect/token', + clientId: environment.auth.clientId, + clientSecret: environment.auth.clientSecret ?? '', + storage: injector.get(), + dio: injector.get().dio + ); + } + + late OAuth _auth; + late EnvironmentService _environmentService; + + @override + void onInit() { + super.onInit(); + _environmentService + .createOnUpdateStream + .map((env) => env.auth) + .listen((auth) { + _auth.tokenUrl = '${auth.getAuthority()}connect/token'; + _auth.clientId = auth.clientId; + _auth.clientSecret = auth.clientSecret ?? ''; + }); + } + + @override + Future password(LoginParams params) { + return _auth.requestTokenAndSave(authlib.PasswordGrant( + username: params.username, + password: params.password, + )).then((res) { + return Token( + accessToken: res.accessToken!, + refreshToken: res.refreshToken, + expiration: res.expiration, + tokenType: 'Bearer', + ); + }); + } + + @override + Future portal(PortalLoginParams params) { + return _auth.requestTokenAndSave(PortalPasswordGrant( + username: params.username, + password: params.password, + enterpriseId: params.enterpriseId, + )).then((res) { + return Token( + accessToken: res.accessToken!, + refreshToken: res.refreshToken, + expiration: res.expiration, + tokenType: 'Bearer', + ); + }).catchError((error) { + var portalProviders = (jsonDecode(error.response.data["Enterprises"]) as List) + .map((e) => PortalLoginProvider.fromJson(e)).toList(); + throw PortalLoginException(portalProviders); + }, test:(error) { + var err = error as dynamic; + if (err?.response?.statusCode == 400 && err?.response?.data != null && + err?.response?.data["Enterprises"] != null) { + return true; + } + return false; + }); + } + + @override + Future phoneNumber(SmsLoginParams params) { + return _auth.requestTokenAndSave(SmsGrant( + phoneNumber: params.phonenumber, + code: params.code, + )).then((res) { + return Token( + accessToken: res.accessToken!, + refreshToken: res.refreshToken, + expiration: res.expiration, + tokenType: 'Bearer', + ); + }); + } + + @override + Future refreshToken(RefreshTokenParams params) { + return _auth.requestTokenAndSave(authlib.RefreshTokenGrant( + refreshToken: params.refreshToken, + )).then((res) { + return Token( + accessToken: res.accessToken!, + refreshToken: res.refreshToken, + expiration: res.expiration, + tokenType: 'Bearer', + ); + }); + } +} \ No newline at end of file diff --git a/apps/flutter/oauth/lib/services/index.dart b/apps/flutter/oauth/lib/services/index.dart new file mode 100644 index 000000000..219851652 --- /dev/null +++ b/apps/flutter/oauth/lib/services/index.dart @@ -0,0 +1,2 @@ +export 'auth.service.oauth.dart'; +export 'oauth.storage.service.dart'; \ No newline at end of file diff --git a/apps/flutter/oauth/lib/services/oauth.storage.service.dart b/apps/flutter/oauth/lib/services/oauth.storage.service.dart new file mode 100644 index 000000000..0b73a842f --- /dev/null +++ b/apps/flutter/oauth/lib/services/oauth.storage.service.dart @@ -0,0 +1,62 @@ +import 'package:core/models/index.dart'; +import 'package:core/services/index.dart'; +import 'package:core/services/service.base.dart'; +import 'package:oauth_dio/oauth_dio.dart'; +import 'package:rxdart/rxdart.dart'; + +class OAuthStorageService extends ServiceBase implements OAuthStorage { + OAuthStorageService(super._injector); + + SessionService get _sessionService => resolve(); + RestService get _restService => resolve(); + + @override + void onInit() { + super.onInit(); + _sessionService.getToken$() + .whereNotNull() + .switchMap((token) => Stream.fromFuture(userProfile())) + .listen((profile) async { + _sessionService.setProfile(profile); + }); + } + + @override + Future clear() { + return Future.sync(() => _sessionService.setToken(null)); + } + + @override + Future fetch() { + return Future.sync(() { + var token = _sessionService.token; + if (token == null) return null; + return OAuthToken( + accessToken: token.accessToken, + refreshToken: token.refreshToken, + expiration: token.expiration, + ); + }); + } + + @override + Future save(OAuthToken token) { + return Future.sync(() { + _sessionService.setToken(Token( + accessToken: token.accessToken!, + refreshToken: token.refreshToken, + tokenType: 'Bearer', + expiration: token.expiration)); + + return token; + }); + } + + Future userProfile() { + return _restService.request( + method: HttpMethod.GET, + url: '/connect/userinfo', + transformer: (res) => UserProfile.fromJson(res.data) + ); + } +} \ No newline at end of file diff --git a/apps/flutter/oauth/lib/utils/index.dart b/apps/flutter/oauth/lib/utils/index.dart new file mode 100644 index 000000000..e69de29bb diff --git a/apps/flutter/oauth/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/oauth/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/oauth/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.h b/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/apps/flutter/oauth/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/oauth/linux/flutter/generated_plugins.cmake b/apps/flutter/oauth/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/apps/flutter/oauth/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/apps/flutter/oauth/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/apps/flutter/oauth/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 000000000..9010f1f77 --- /dev/null +++ b/apps/flutter/oauth/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\oauth +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/oauth/macos/Flutter/ephemeral/flutter_export_environment.sh b/apps/flutter/oauth/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100644 index 000000000..ce7101c21 --- /dev/null +++ b/apps/flutter/oauth/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\oauth" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/oauth/pubspec.yaml b/apps/flutter/oauth/pubspec.yaml new file mode 100644 index 000000000..3602ff0e3 --- /dev/null +++ b/apps/flutter/oauth/pubspec.yaml @@ -0,0 +1,64 @@ +name: oauth +description: A new Flutter package project. +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: '>=3.0.5 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + + core: + path: '../core' + dio: ^4.0.0 + oauth_dio: ^0.2.7 + rxdart: ^0.27.7 + +dependency_overrides: + dio: ^4.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.cc b/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.h b/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/apps/flutter/oauth/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/oauth/windows/flutter/generated_plugins.cmake b/apps/flutter/oauth/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/apps/flutter/oauth/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/apps/flutter/platform/.gitignore b/apps/flutter/platform/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/apps/flutter/platform/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/apps/flutter/platform/.metadata b/apps/flutter/platform/.metadata new file mode 100644 index 000000000..9596faeed --- /dev/null +++ b/apps/flutter/platform/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: package diff --git a/apps/flutter/platform/CHANGELOG.md b/apps/flutter/platform/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/apps/flutter/platform/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/apps/flutter/platform/LICENSE b/apps/flutter/platform/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/apps/flutter/platform/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/apps/flutter/platform/README.md b/apps/flutter/platform/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/apps/flutter/platform/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/apps/flutter/platform/analysis_options.yaml b/apps/flutter/platform/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/apps/flutter/platform/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/apps/flutter/platform/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java b/apps/flutter/platform/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java new file mode 100644 index 000000000..7eb0d9f93 --- /dev/null +++ b/apps/flutter/platform/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java @@ -0,0 +1,25 @@ +package io.flutter.plugins; + +import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugins.pathprovider.PathProviderPlugin; + +/** + * Generated file. Do not edit. + */ +public final class GeneratedPluginRegistrant { + public static void registerWith(PluginRegistry registry) { + if (alreadyRegisteredWith(registry)) { + return; + } + PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin")); + } + + private static boolean alreadyRegisteredWith(PluginRegistry registry) { + final String key = GeneratedPluginRegistrant.class.getCanonicalName(); + if (registry.hasPlugin(key)) { + return true; + } + registry.registrarFor(key); + return false; + } +} diff --git a/apps/flutter/platform/android/local.properties b/apps/flutter/platform/android/local.properties new file mode 100644 index 000000000..1a3be4ff1 --- /dev/null +++ b/apps/flutter/platform/android/local.properties @@ -0,0 +1,2 @@ +sdk.dir=C:\\Users\\eddlevol\\AppData\\Local\\Android\\sdk +flutter.sdk=D:\\Sdk\\Flutter \ No newline at end of file diff --git a/apps/flutter/platform/ios/Flutter/Generated.xcconfig b/apps/flutter/platform/ios/Flutter/Generated.xcconfig new file mode 100644 index 000000000..baef6d14b --- /dev/null +++ b/apps/flutter/platform/ios/Flutter/Generated.xcconfig @@ -0,0 +1,14 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\platform +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib\main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 +EXCLUDED_ARCHS[sdk=iphoneos*]=armv7 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/platform/ios/Flutter/flutter_export_environment.sh b/apps/flutter/platform/ios/Flutter/flutter_export_environment.sh new file mode 100644 index 000000000..fd6f6578c --- /dev/null +++ b/apps/flutter/platform/ios/Flutter/flutter_export_environment.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\platform" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib\main.dart" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.h b/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.h new file mode 100644 index 000000000..7a8909271 --- /dev/null +++ b/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.h @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GeneratedPluginRegistrant_h +#define GeneratedPluginRegistrant_h + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GeneratedPluginRegistrant : NSObject ++ (void)registerWithRegistry:(NSObject*)registry; +@end + +NS_ASSUME_NONNULL_END +#endif /* GeneratedPluginRegistrant_h */ diff --git a/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.m b/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.m new file mode 100644 index 000000000..c0d0cbad8 --- /dev/null +++ b/apps/flutter/platform/ios/Runner/GeneratedPluginRegistrant.m @@ -0,0 +1,21 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#import "GeneratedPluginRegistrant.h" + +#if __has_include() +#import +#else +@import path_provider_foundation; +#endif + +@implementation GeneratedPluginRegistrant + ++ (void)registerWithRegistry:(NSObject*)registry { + [PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]]; +} + +@end diff --git a/apps/flutter/platform/lib/index.dart b/apps/flutter/platform/lib/index.dart new file mode 100644 index 000000000..00cf72490 --- /dev/null +++ b/apps/flutter/platform/lib/index.dart @@ -0,0 +1 @@ +export 'platform.module.dart'; \ No newline at end of file diff --git a/apps/flutter/platform/lib/modes/menu.dto.dart b/apps/flutter/platform/lib/modes/menu.dto.dart new file mode 100644 index 000000000..487587175 --- /dev/null +++ b/apps/flutter/platform/lib/modes/menu.dto.dart @@ -0,0 +1,132 @@ +import 'package:core/index.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'menu.dto.g.dart'; + +abstract class RouteDto extends EntityDto { + RouteDto({ + required super.id, + required this.path, + required this.name, + required this.displayName, + this.description = '', + this.meta = const {}, + }); + String path; + String name; + String displayName; + String? description; + String? redirect; + Map? meta; +} + +@JsonSerializable() +class MenuDto extends RouteDto { + MenuDto({ + required super.id, + required super.path, + required super.name, + required super.displayName, + required this.code, + required this.component, + required this.framework, + required this.layoutId, + this.parentId, + this.isPublic = false, + this.startup = false, + super.description = '', + super.meta = const {}, + }); + String code; + String component; + String framework; + String? parentId; + String layoutId; + bool isPublic; + bool startup; + + factory MenuDto.fromJson(Map json) => _$MenuDtoFromJson(json); + + @override + Map toJson({ Object? Function(String value)? toJsonTPrimaryKey }) => _$MenuDtoToJson(this); +} + +@JsonSerializable() +class UserFavoriteMenuDto extends AuditedEntityDto { + UserFavoriteMenuDto({ + required super.id, + required super.creationTime, + super.creatorId, + super.lastModificationTime, + super.lastModifierId, + required this.menuId, + required this.userId, + this.framework, + required this.name, + required this.path, + this.aliasName, + this.icon, + this.color, + this.displayName, + }); + String menuId; + String userId; + String? framework; + String name; + String path; + String? aliasName; + String? icon; + String? color; + String? displayName; + + factory UserFavoriteMenuDto.fromJson(Map json) => _$UserFavoriteMenuDtoFromJson(json); + + @override + Map toJson({ Object? Function(String value)? toJsonTPrimaryKey }) => _$UserFavoriteMenuDtoToJson(this); +} + +abstract class UserFavoriteMenuCreateOrUpdateDto { + UserFavoriteMenuCreateOrUpdateDto({ + required this.menuId, + this.color, + this.aliasName, + this.icon, + }); + String menuId; + String? color; + String? aliasName; + String? icon; +} + +@JsonSerializable() +class UserFavoriteMenuCreateDto extends UserFavoriteMenuCreateOrUpdateDto { + UserFavoriteMenuCreateDto({ + required super.menuId, + this.framework, + super.color, + super.aliasName, + super.icon, + }); + String? framework; + + factory UserFavoriteMenuCreateDto.fromJson(Map json) => _$UserFavoriteMenuCreateDtoFromJson(json); + + Map toJson() => _$UserFavoriteMenuCreateDtoToJson(this); +} + +@JsonSerializable() +class UserFavoriteMenuUpdateDto extends UserFavoriteMenuCreateOrUpdateDto implements IHasConcurrencyStamp { + UserFavoriteMenuUpdateDto({ + required super.menuId, + super.color, + super.aliasName, + super.icon, + this.concurrencyStamp, + }); + @override + String? concurrencyStamp; + + factory UserFavoriteMenuUpdateDto.fromJson(Map json) => _$UserFavoriteMenuUpdateDtoFromJson(json); + + Map toJson() => _$UserFavoriteMenuUpdateDtoToJson(this); +} \ No newline at end of file diff --git a/apps/flutter/platform/lib/modes/menu.dto.g.dart b/apps/flutter/platform/lib/modes/menu.dto.g.dart new file mode 100644 index 000000000..9128395ed --- /dev/null +++ b/apps/flutter/platform/lib/modes/menu.dto.g.dart @@ -0,0 +1,119 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'menu.dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MenuDto _$MenuDtoFromJson(Map json) => MenuDto( + id: json['id'] as String, + path: json['path'] as String, + name: json['name'] as String, + displayName: json['displayName'] as String, + code: json['code'] as String, + component: json['component'] as String, + framework: json['framework'] as String, + layoutId: json['layoutId'] as String, + parentId: json['parentId'] as String?, + isPublic: json['isPublic'] as bool? ?? false, + startup: json['startup'] as bool? ?? false, + description: json['description'] as String? ?? '', + meta: json['meta'] as Map? ?? const {}, + )..redirect = json['redirect'] as String?; + +Map _$MenuDtoToJson(MenuDto instance) => { + 'id': instance.id, + 'path': instance.path, + 'name': instance.name, + 'displayName': instance.displayName, + 'description': instance.description, + 'redirect': instance.redirect, + 'meta': instance.meta, + 'code': instance.code, + 'component': instance.component, + 'framework': instance.framework, + 'parentId': instance.parentId, + 'layoutId': instance.layoutId, + 'isPublic': instance.isPublic, + 'startup': instance.startup, + }; + +UserFavoriteMenuDto _$UserFavoriteMenuDtoFromJson(Map json) => + UserFavoriteMenuDto( + id: json['id'] as String, + creationTime: DateTime.parse(json['creationTime'] as String), + creatorId: json['creatorId'] as String?, + lastModificationTime: json['lastModificationTime'] == null + ? null + : DateTime.parse(json['lastModificationTime'] as String), + lastModifierId: json['lastModifierId'] as String?, + menuId: json['menuId'] as String, + userId: json['userId'] as String, + framework: json['framework'] as String?, + name: json['name'] as String, + path: json['path'] as String, + aliasName: json['aliasName'] as String?, + icon: json['icon'] as String?, + color: json['color'] as String?, + displayName: json['displayName'] as String?, + ); + +Map _$UserFavoriteMenuDtoToJson( + UserFavoriteMenuDto instance) => + { + 'id': instance.id, + 'creationTime': instance.creationTime.toIso8601String(), + 'creatorId': instance.creatorId, + 'lastModificationTime': instance.lastModificationTime?.toIso8601String(), + 'lastModifierId': instance.lastModifierId, + 'menuId': instance.menuId, + 'userId': instance.userId, + 'framework': instance.framework, + 'name': instance.name, + 'path': instance.path, + 'aliasName': instance.aliasName, + 'icon': instance.icon, + 'color': instance.color, + 'displayName': instance.displayName, + }; + +UserFavoriteMenuCreateDto _$UserFavoriteMenuCreateDtoFromJson( + Map json) => + UserFavoriteMenuCreateDto( + menuId: json['menuId'] as String, + framework: json['framework'] as String?, + color: json['color'] as String?, + aliasName: json['aliasName'] as String?, + icon: json['icon'] as String?, + ); + +Map _$UserFavoriteMenuCreateDtoToJson( + UserFavoriteMenuCreateDto instance) => + { + 'menuId': instance.menuId, + 'color': instance.color, + 'aliasName': instance.aliasName, + 'icon': instance.icon, + 'framework': instance.framework, + }; + +UserFavoriteMenuUpdateDto _$UserFavoriteMenuUpdateDtoFromJson( + Map json) => + UserFavoriteMenuUpdateDto( + menuId: json['menuId'] as String, + color: json['color'] as String?, + aliasName: json['aliasName'] as String?, + icon: json['icon'] as String?, + concurrencyStamp: json['concurrencyStamp'] as String?, + ); + +Map _$UserFavoriteMenuUpdateDtoToJson( + UserFavoriteMenuUpdateDto instance) => + { + 'menuId': instance.menuId, + 'color': instance.color, + 'aliasName': instance.aliasName, + 'icon': instance.icon, + 'concurrencyStamp': instance.concurrencyStamp, + }; diff --git a/apps/flutter/platform/lib/modes/state.dart b/apps/flutter/platform/lib/modes/state.dart new file mode 100644 index 000000000..68e5bffe9 --- /dev/null +++ b/apps/flutter/platform/lib/modes/state.dart @@ -0,0 +1,15 @@ +import 'package:platforms/modes/menu.dto.dart'; + +class FavoriteMenuState { + FavoriteMenuState({ + this.menus = const [], + }); + List menus; +} + +class MenuState { + MenuState({ + this.menus = const [], + }); + List menus; +} diff --git a/apps/flutter/platform/lib/platform.module.dart b/apps/flutter/platform/lib/platform.module.dart new file mode 100644 index 000000000..72916f85f --- /dev/null +++ b/apps/flutter/platform/lib/platform.module.dart @@ -0,0 +1,14 @@ +import 'package:core/modularity/module.dart'; +import 'package:platforms/proxy/index.dart'; +import 'package:platforms/services/index.dart'; + +class PlatformModule extends Module { + @override + void configureServices() { + lazyInject((injector) => MenuService(injector)); + lazyInject((injector) => FavoriteMenuService(injector)); + + lazyInject((injector) => MenuStateService(injector)); + lazyInject((injector) => FavoriteMenuStateService(injector)); + } +} \ No newline at end of file diff --git a/apps/flutter/platform/lib/proxy/favorite.menu.service.dart b/apps/flutter/platform/lib/proxy/favorite.menu.service.dart new file mode 100644 index 000000000..e23b34f7c --- /dev/null +++ b/apps/flutter/platform/lib/proxy/favorite.menu.service.dart @@ -0,0 +1,51 @@ +import 'package:core/dependency/index.dart'; +import 'package:core/models/abp.dto.dart'; +import 'package:core/models/request.dart'; +import 'package:core/services/index.dart'; +import 'package:platforms/modes/menu.dto.dart'; + +class FavoriteMenuService { + FavoriteMenuService(this._injector); + + final Injector _injector; + + RestService get _restService => _injector.get(); + + Future createMyFavoriteMenu(UserFavoriteMenuCreateDto input, { RequestOptions? requestOptions }) { + return _restService.request( + url: '/api/platform/menus/favorites/my-favorite-menu', + method: HttpMethod.POST, + data: input, + requestOptions: requestOptions, + transformer: (response) => UserFavoriteMenuDto.fromJson(response.data), + ); + } + + Future deleteMyFavoriteMenu(String menuId, { RequestOptions? requestOptions }) { + return _restService.request( + url: '/api/platform/menus/favorites/my-favorite-menu/$menuId', + method: HttpMethod.DELETE, + requestOptions: requestOptions, + ); + } + + Future> getMyFavoriteMenuList(String framework, { RequestOptions? requestOptions }) { + return _restService.request( + url: '/api/platform/menus/favorites/my-favorite-menus?framework=$framework', + method: HttpMethod.GET, + requestOptions: requestOptions, + transformer: (response) => ListResultDto.fromJson(response.data, + fromJsonT: (json) => UserFavoriteMenuDto.fromJson(json as Map)), + ); + } + + Future updateMyFavoriteMenu(UserFavoriteMenuUpdateDto input, { RequestOptions? requestOptions }) { + return _restService.request( + url: '/api/platform/menus/favorites/my-favorite-menu', + method: HttpMethod.PUT, + data: input, + requestOptions: requestOptions, + transformer: (response) => UserFavoriteMenuDto.fromJson(response.data), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/platform/lib/proxy/index.dart b/apps/flutter/platform/lib/proxy/index.dart new file mode 100644 index 000000000..c8f837ece --- /dev/null +++ b/apps/flutter/platform/lib/proxy/index.dart @@ -0,0 +1,2 @@ +export 'favorite.menu.service.dart'; +export 'menu.service.dart'; \ No newline at end of file diff --git a/apps/flutter/platform/lib/proxy/menu.service.dart b/apps/flutter/platform/lib/proxy/menu.service.dart new file mode 100644 index 000000000..265f4e109 --- /dev/null +++ b/apps/flutter/platform/lib/proxy/menu.service.dart @@ -0,0 +1,23 @@ +import 'package:core/dependency/index.dart'; +import 'package:core/models/abp.dto.dart'; +import 'package:core/models/request.dart'; +import 'package:core/services/rest.service.dart'; +import 'package:platforms/modes/menu.dto.dart'; + +class MenuService { + MenuService(this._injector); + + final Injector _injector; + + RestService get _restService => _injector.get(); + + Future> getCurrentUserMenuList(String framework, { RequestOptions? requestOptions }) { + return _restService.request( + url: '/api/platform/menus/by-current-user?framework=$framework', + method: HttpMethod.GET, + requestOptions: requestOptions, + transformer: (response) => ListResultDto.fromJson(response.data, + fromJsonT: (json) => MenuDto.fromJson(json as Map)), + ); + } +} \ No newline at end of file diff --git a/apps/flutter/platform/lib/services/favorite.menu.state.service.dart b/apps/flutter/platform/lib/services/favorite.menu.state.service.dart new file mode 100644 index 000000000..1114b2403 --- /dev/null +++ b/apps/flutter/platform/lib/services/favorite.menu.state.service.dart @@ -0,0 +1,36 @@ +import 'package:core/services/environment.service.dart'; +import 'package:core/services/service.base.dart'; +import 'package:core/utils/index.dart'; +import 'package:platforms/modes/state.dart'; +import 'package:platforms/modes/menu.dto.dart'; +import 'package:platforms/proxy/favorite.menu.service.dart'; + +class FavoriteMenuStateService extends ServiceBase { + FavoriteMenuStateService(super.injector); + + final InternalStore _state = InternalStore(state: FavoriteMenuState()); + + EnvironmentService get _environmentService => resolve(); + FavoriteMenuService get _favoriteMenuService => resolve(); + + @override + void onInit() { + super.onInit(); + refreshState(); + } + + Future refreshState() async { + var environment = _environmentService.getEnvironment(); + var framework = environment.application.framework ?? 'flutter'; + var result = await _favoriteMenuService.getMyFavoriteMenuList(framework); + _state.patch((state) => state.menus = result.items); + } + + List getFavoriteMenus() { + return _state.state.menus; + } + + Stream> getFavoriteMenus$() { + return _state.sliceState((state) => state.menus); + } +} \ No newline at end of file diff --git a/apps/flutter/platform/lib/services/index.dart b/apps/flutter/platform/lib/services/index.dart new file mode 100644 index 000000000..ec0933b60 --- /dev/null +++ b/apps/flutter/platform/lib/services/index.dart @@ -0,0 +1,2 @@ +export 'favorite.menu.state.service.dart'; +export 'menu.state.service.dart'; \ No newline at end of file diff --git a/apps/flutter/platform/lib/services/menu.state.service.dart b/apps/flutter/platform/lib/services/menu.state.service.dart new file mode 100644 index 000000000..d6575bb67 --- /dev/null +++ b/apps/flutter/platform/lib/services/menu.state.service.dart @@ -0,0 +1,36 @@ +import 'package:core/services/environment.service.dart'; +import 'package:core/services/service.base.dart'; +import 'package:core/utils/index.dart'; +import 'package:platforms/modes/state.dart'; +import 'package:platforms/modes/menu.dto.dart'; +import 'package:platforms/proxy/index.dart'; + +class MenuStateService extends ServiceBase { + MenuStateService(super.injector); + + final InternalStore _state = InternalStore(state: MenuState()); + + EnvironmentService get _environmentService => resolve(); + MenuService get _menuService => resolve(); + + @override + void onInit() { + super.onInit(); + refreshState(); + } + + Future refreshState() async { + var environment = _environmentService.getEnvironment(); + var framework = environment.application.framework ?? 'flutter'; + var result = await _menuService.getCurrentUserMenuList(framework); + _state.patch((state) => state.menus = result.items); + } + + List getMyMenus() { + return _state.state.menus; + } + + Stream> getMyMenus$() { + return _state.sliceState((state) => state.menus); + } +} \ No newline at end of file diff --git a/apps/flutter/platform/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/apps/flutter/platform/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..4a72bc1ee --- /dev/null +++ b/apps/flutter/platform/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/eddlevol/AppData/Local/Pub/Cache/hosted/pub.flutter-io.cn/path_provider_linux-2.1.11/ \ No newline at end of file diff --git a/apps/flutter/platform/linux/flutter/generated_plugin_registrant.cc b/apps/flutter/platform/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/apps/flutter/platform/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/apps/flutter/platform/linux/flutter/generated_plugin_registrant.h b/apps/flutter/platform/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/apps/flutter/platform/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/platform/linux/flutter/generated_plugins.cmake b/apps/flutter/platform/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/apps/flutter/platform/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/apps/flutter/platform/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/apps/flutter/platform/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 000000000..0446340c3 --- /dev/null +++ b/apps/flutter/platform/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=D:\Sdk\Flutter +FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\platform +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/apps/flutter/platform/macos/Flutter/ephemeral/flutter_export_environment.sh b/apps/flutter/platform/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100644 index 000000000..56916136a --- /dev/null +++ b/apps/flutter/platform/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=D:\Sdk\Flutter" +export "FLUTTER_APPLICATION_PATH=D:\C Sharp\Open-Sources\abp-next-admin\apps\flutter\platform" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/apps/flutter/platform/pubspec.yaml b/apps/flutter/platform/pubspec.yaml new file mode 100644 index 000000000..faf56fe5e --- /dev/null +++ b/apps/flutter/platform/pubspec.yaml @@ -0,0 +1,66 @@ +name: platforms +description: A new Flutter package project. +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: '>=3.0.5 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + core: + path: '../core' + components: + path: '../components' + + get: ^4.6.5 + rxdart: ^0.27.7 + json_annotation: ^4.8.1 + date_format: ^2.0.7 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + build_runner: ^2.4.5 + json_serializable: ^6.7.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/apps/flutter/platform/windows/flutter/generated_plugin_registrant.cc b/apps/flutter/platform/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/apps/flutter/platform/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/apps/flutter/platform/windows/flutter/generated_plugin_registrant.h b/apps/flutter/platform/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/apps/flutter/platform/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/apps/flutter/platform/windows/flutter/generated_plugins.cmake b/apps/flutter/platform/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/apps/flutter/platform/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/UserNotificationDto.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/UserNotificationDto.cs index 9eb5b651a..1eff8c49d 100644 --- a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/UserNotificationDto.cs +++ b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Application.Contracts/LINGYUN/Abp/Notifications/Dto/UserNotificationDto.cs @@ -8,8 +8,8 @@ public class UserNotificationDto public string Id { get; set; } public NotificationData Data { get; set; } public DateTime CreationTime { get; set; } - public NotificationLifetime Lifetime { get; set; } public NotificationType Type { get; set; } public NotificationSeverity Severity { get; set; } public NotificationReadState State { get; set; } + public NotificationContentType ContentType { get; set; } } diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.EntityFrameworkCore/LINGYUN/Abp/Notifications/EntityFrameworkCore/EfCoreUserNotificationRepository.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.EntityFrameworkCore/LINGYUN/Abp/Notifications/EntityFrameworkCore/EfCoreUserNotificationRepository.cs index 577fcac76..ee61ea29d 100644 --- a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.EntityFrameworkCore/LINGYUN/Abp/Notifications/EntityFrameworkCore/EfCoreUserNotificationRepository.cs +++ b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.EntityFrameworkCore/LINGYUN/Abp/Notifications/EntityFrameworkCore/EfCoreUserNotificationRepository.cs @@ -176,7 +176,7 @@ on un.NotificationId equals n.NotificationId Severity = n.Severity, State = un.ReadStatus, Type = n.Type, - ContentType = n.ContentType + ContentType = n.ContentType, }; return await notifilerQuery