diff --git a/.gitignore b/.gitignore
index 36ad4901..fe733f8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,7 @@
*.ipr
*.iws
.idea/
-
+/lib/temp
# 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.
@@ -29,7 +29,13 @@
.pub-cache/
.pub/
/build/
+/android/app/.cxx/
/lib/tools/
/lib/res/constant/github_client_config.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
+
+/build_tools
+/libs
+/pubspec_overrides.yaml
+modules/game_system
diff --git a/README-EN.md b/README-EN.md
new file mode 100644
index 00000000..11044f8f
--- /dev/null
+++ b/README-EN.md
@@ -0,0 +1,239 @@
+
+
+ FlutterUnit🔖
+
+ ⭐️ All Platform Flutter Experience App ⭐️
+
+
+
+FlutterUnit is a cross-platform experience app, Here, you can fully explore the creativity that Flutter offers.
+
+
+
+
+
+
+
+
+
+ Download v3.0.0 :
+ [Android] •
+ [iOS] •
+ [MacOS] •
+ [Windows] •
+ [Web]
+
+
+
+
+---
+
+
+### Env and Build
+
+#### Flutter Version
+
+```
+·]>> flutter --version
+Flutter 3.32.0 • channel stable • https://github.com/flutter/flutter.git
+Framework • revision be698c48a6 (2 days ago) • 2025-05-19 12:59:14 -0700
+Engine • revision 1881800949 (2 days ago) • 2025-05-19 10:54:07 -0700
+Tools • Dart 3.8.0 • DevTools 2.45.1
+```
+
+#### Build Application
+
+```
+·]>> git clone https://github.com/toly1994328/FlutterUnit.git
+·]>> cd FlutterUnit
+
+Build Android:
+·]>> flutter build apk --target-platform --split-per-abi
+Build iOS:
+·]>> flutter build ios
+Build Windows:
+·]>> flutter build windows
+Build Linux:
+·]>> flutter build linux
+Build web:
+·]>> flutter build web
+```
+
+
+#### My Flutter Books
+- 🔥 [免费] [掘金小册 -《Flutter 入门教程》](https://juejin.cn/book/7212822723330834487)
+- 🔥 [掘金小册 -《Flutter 语言基础 - 梦始之地》](https://juejin.cn/book/6844733827617652750)
+- 🔥 [掘金小册 -《Flutter 绘制指南 - 妙笔生花》](https://juejin.im/book/6844733827265331214)
+- 🔥 [掘金小册 -《Flutter 手势探索 - 执掌天下》](https://juejin.cn/book/6896378716427911181)
+- 🔥 [掘金小册 -《Flutter 动画探索 - 流光幻影》](https://juejin.cn/book/6965102582473687071)
+- 🔥 [掘金小册 -《Flutter 滑动探索 - 珠联璧合》](https://juejin.cn/book/6984685333312962573)
+- 🔥 [掘金小册 -《Flutter 布局探索 - 薪火相传》](https://juejin.cn/book/7075958265250578469)
+- 🔥 [掘金小册 -《Flutter 渲染机制 - 聚沙成塔》](https://juejin.cn/book/6965102582473687071)
+
+---
+
+- [Flutter环境配置](https://github.com/toly1994328/FlutterUnit/issues/22)
+- [Flutter实用插件集录 ](https://github.com/toly1994328/FlutterUnit/issues/41)
+- [Flutter要点集录 ](https://github.com/toly1994328/FlutterUnit/labels/point)
+
+
+---
+
+
+#### MacOS 桌面版本组件界面
+
+
+
+#### Windows 桌面版本组件界面
+
+
+
+
+> 开源不易,请我喝咖啡 ~
+
+
+
+
+
+#### Star History
+
+[](https://star-history.com/#toly1994328/FlutterUnit&Date)
+
+### 一、组件的展示页面
+
+#### 1. `300+组件收录`
+
+> Flutter源码中的可用的组件一共350个左右,纷繁复杂,也没有明确的分类标准
+FlutterUnit 对`大大小小,常用不常用`的组件能收的尽量收录。并`根据个人感觉进行评星 `
+`目前收录组件306个`,每个都有至少一个演示展现和代码展示。
+
+| . | . | . |
+|------|------------|------------|
+| | |  |
+
+---
+
+#### 2. 组件详情页
+
+> `213个组件`全部都有详情页。对于重要的组件会详细展现
+一般都会有某个演示对应的组件和属性,尽量做到细致,如果有需要补充,欢迎联系我。
+`最重要的是: 所有的演示展现都是Flutter的组件形成的,而非图片,这就意味着可操作性更高。`
+
+| . | . | . |
+|------|------------|------------|
+| | |  |
+|  |  ||
+
+---
+
+#### 3. 组件的可操作性
+
+> 对一些操作交互的组件或有可操作性的某些组件,`提供操作演示`
+
+| . | . | . |
+|------|------------|------------|
+| | | |
+|  |  ||
+
+---
+
+#### 4. 相关组件的关联切换
+> `相关组件通过link to 可以进行切换, 满足你的探索欲。`
+如果有的关联未加入,欢迎联系我,对我来说,加个数字就行了。
+
+| . | . | . |
+|------|------------|------------|
+||| |
+
+
+---
+
+#### 5. 代码的查看和分享
+> 激动人心的是,你可以通过右侧的图标`展开/隐藏 实现下面效果的代码`
+并且`支持分享`,如果你想亲自体验,so,easy ! 而且`代码高亮样式可以自定义`。
+
+
+| . | . | . |
+|------|------------|------------|
+| | | |
+
+---
+
+
+### 二、全局配置
+
+#### 1. 颜色主题
+> 只提供八种颜色,可在`右滑菜单页`的`我的主题`配置,`可以拓展`
+
+| . | . | . |
+|------|------------|------------|
+| |  |  |
+
+---
+
+
+#### 2.字体配置
+
+> 支持全局字体设置,`可以拓展`
+
+| . | . | . |
+|------|------------|------------|
+| |  | |
+---
+
+
+#### 3.item样式设置
+
+> 支持item样式设置,`可以拓展,支持征集`,详见`Flutter Unit 1.0 征集方案`
+
+| . | . | . |
+|------|------------|------------|
+|| | |
+---
+
+#### 4.代码面板风格设置
+
+> 支持代码风格设置,`可以拓展,支持征集`,详见`Flutter Unit 1.0 征集方案`
+
+| . | . |
+|------|------------|
+|| |
+||
+
+---
+
+
+
+### 三、搜索与收藏功能
+
+
+#### 1.搜索功能
+
+> 由于Flutter中Widget比较杂乱,不太好分类,所以搜索是非常重要的
+另外可以根据星级进行过滤,支持多选。目前正在考虑根据功能分类,之后会有所完善。
+
+
+| . | . | . |
+|------|------------|------------|
+| | |  |
+
+---
+
+#### 2.收藏功能
+
+| 添加收藏集 | 修改收藏集 | 删除收藏集 |
+|------|------------|------------|
+|  |  |  |
+
+| 长按右菜单滑页 | 长按左菜单滑页 | 详情内长按展示收藏菜单 |
+|------|------------|------------|
+|  | |  |
+
+| 删除与数据同步 | 组件加入收藏集 | 收藏集支持多选 |
+|------|------------|------------|
+|  |  |  |
+
+> `FlutterUnit 2.0 `目前基本就是这么多功能,可以在Github中下载打包后的apk玩玩
+希望能对你的Flutter学习有所帮助。
+
+---
diff --git a/README.md b/README.md
index 7fca74a3..9e430602 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,65 @@
+
+
+ FlutterUnit
+
+ ⭐️ 全平台 Flutter 探索应用 ⭐️
+
+
+
+FlutterUnit 是一个全平台体验应用,你可以在这里尽情体验 Flutter 带来的创造力。
+
+
+
+
+
+
+
+
+
+ 下载 App:
+ [Android] •
+ [iOS] •
+ [MacOS] •
+ [Windows] •
+ [Web]
+
+
+
+
+---
+
+### 环境与构建
+
+#### Flutter 版本
+
+```
+·]>> flutter --version
+Flutter 3.32.0 • channel stable • https://github.com/flutter/flutter.git
+Framework • revision be698c48a6 (2 days ago) • 2025-05-19 12:59:14 -0700
+Engine • revision 1881800949 (2 days ago) • 2025-05-19 10:54:07 -0700
+Tools • Dart 3.8.0 • DevTools 2.45.1
+```
+
+#### 构建应用
+
+```
+·]>> git clone https://github.com/toly1994328/FlutterUnit.git
+·]>> cd FlutterUnit
+
+Build Android:
+·]>> flutter build apk --target-platform --split-per-abi
+Build iOS:
+·]>> flutter build ios
+Build Windows:
+·]>> flutter build windows
+Build Linux:
+·]>> flutter build linux
+Build web:
+·]>> flutter build web
+```
#### Flutter Unit 周边
+- 🔥 [免费] [掘金小册 -《Flutter 入门教程》](https://juejin.cn/book/7212822723330834487)
- 🔥 [掘金小册 -《Flutter 语言基础 - 梦始之地》](https://juejin.cn/book/6844733827617652750)
- 🔥 [掘金小册 -《Flutter 绘制指南 - 妙笔生花》](https://juejin.im/book/6844733827265331214)
- 🔥 [掘金小册 -《Flutter 手势探索 - 执掌天下》](https://juejin.cn/book/6896378716427911181)
@@ -14,27 +74,6 @@
- [Flutter实用插件集录 ](https://github.com/toly1994328/FlutterUnit/issues/41)
- [Flutter要点集录 ](https://github.com/toly1994328/FlutterUnit/labels/point)
-### FlutterUnit 下载体验: 复制链接,在浏览器下载~
-
-| 平台类型 | 下载地址 | 项目分支地址 | 相关文章 |
-|------|------------|------|------------|
-| Android版 | http://toly1994.com/file/FlutterUnit.apk |[flutter_unit](https://github.com/toly1994328/FlutterUnit)| [《FlutterUnit食用指南》](https://juejin.im/post/6844904147045597191)|
-| iOS版 | 暂未提供,可自己下载项目运行 |[flutter_unit](https://github.com/toly1994328/FlutterUnit)| [《FlutterUnit 食用指南》](https://juejin.im/post/6844904147045597191)|
-| MacOS版 | http://toly1994.com/file/flutter_unit_mac.zip |[flutter_unit](https://github.com/toly1994328/FlutterUnit/tree/flutter_unit)| [《mac版闪亮登场》](https://juejin.im/post/6844904147817332743)|
-| Windows版 |http://toly1994.com/file/FlutterUnitWin.zip | [flutter_unit](https://github.com/toly1994328/FlutterUnit/tree/flutter_unit) | [《win版闪亮登场》](https://juejin.im/post/6847902222626488327)|
-| Web版 | http://toly1994328.gitee.io/flutter_web | [ flutter_unit_web ](https://github.com/toly1994328/FlutterUnit/tree/flutter_unit_web) | [《web版闪亮登场》](https://juejin.im/post/6859888713980182541)|
-
----
-
-> 当前Flutter 版本
-
-```
-Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git
-Framework • revision b06b8b2710 (10 days ago) • 2023-01-23 16:55:55 -0800
-Engine • revision b24591ed32
-Tools • Dart 2.19.0 • DevTools 2.20.1
-```
-
---
#### MacOS 桌面版本组件界面
@@ -46,6 +85,15 @@ Tools • Dart 2.19.0 • DevTools 2.20.1

+> 开源不易,请我喝咖啡 ~
+
+
+
+
+
+#### Star History
+
+[](https://star-history.com/#toly1994328/FlutterUnit&Date)
### 一、组件的展示页面
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 2fdeaeb0..d54e87f3 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -10,21 +10,13 @@
include: package:flutter_lints/flutter.yaml
linter:
- # The lint rules applied to this project can be customized in the
- # section below to disable rules from the `package:flutter_lints/flutter.yaml`
- # included above or to enable additional rules. A list of all available lints
- # and their documentation is published at
- # https://dart-lang.github.io/linter/lints/index.html.
- #
- # Instead of disabling a lint rule for the entire project in the
- # section below, it can also be suppressed for a single line of code
- # or a specific dart file by using the `// ignore: name_of_lint` and
- # `// ignore_for_file: name_of_lint` syntax on the line or in the file
- # producing the lint.
rules:
avoid_print: false # Uncomment to disable the `avoid_print` rule
file_names: false
- # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+analyzer:
+# exclude:
+# - modules/widget_system/widgets/**
+
+
+
diff --git a/android/app/build.gradle b/android/app/build.gradle
deleted file mode 100644
index b3a3b1d7..00000000
--- a/android/app/build.gradle
+++ /dev/null
@@ -1,70 +0,0 @@
-def localProperties = new Properties()
-def localPropertiesFile = rootProject.file('local.properties')
-if (localPropertiesFile.exists()) {
- localPropertiesFile.withReader('UTF-8') { reader ->
- localProperties.load(reader)
- }
-}
-
-def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
- throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
-
-def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
-if (flutterVersionCode == null) {
- flutterVersionCode = '1'
-}
-
-def flutterVersionName = localProperties.getProperty('flutter.versionName')
-if (flutterVersionName == null) {
- flutterVersionName = '1.0'
-}
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
-
-android {
- compileSdkVersion 33
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- kotlinOptions {
- jvmTarget = '1.8'
- }
-
- sourceSets {
- main.java.srcDirs += 'src/main/kotlin'
- }
-
- defaultConfig {
- // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId "com.toly1994.flutter_unit"
- minSdkVersion 16
- targetSdkVersion 30
- versionCode flutterVersionCode.toInteger()
- versionName flutterVersionName
- multiDexEnabled true
- archivesBaseName = "FlutterUnit.apk"
- }
-
- buildTypes {
- release {
- // TODO: Add your own signing config for the release build.
- // Signing with the debug keys for now, so `flutter run --release` works.
- signingConfig signingConfigs.debug
- }
- }
-}
-
-flutter {
- source '../..'
-}
-
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-}
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
new file mode 100644
index 00000000..d73f8c2d
--- /dev/null
+++ b/android/app/build.gradle.kts
@@ -0,0 +1,53 @@
+plugins {
+ id("com.android.application")
+ id("kotlin-android")
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id("dev.flutter.flutter-gradle-plugin")
+}
+
+android {
+ namespace = "com.toly1994.flutter_unit"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+ }
+
+ kotlinOptions {
+ jvmTarget = JavaVersion.VERSION_11.toString()
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId = "com.toly1994.flutter_unit"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://flutter.dev/to/review-gradle-config.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutter.versionCode
+ versionName = flutter.versionName
+ }
+
+ buildTypes {
+ getByName("release") {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig = signingConfigs.getByName("debug")
+ isShrinkResources = true // 移除未使用的资源
+ isMinifyEnabled = true // 启用 R8 代码压缩
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ ndk {
+ debugSymbolLevel = "none"
+ }
+ }
+ }
+}
+
+flutter {
+ source = "../.."
+}
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 00000000..e9ffa01a
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,2 @@
+-dontwarn javax.annotation.**
+-keep class javax.annotation.** { *; }
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 932ba74d..67873441 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
-
+
+
+
+
@@ -28,6 +30,7 @@
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
+ android:exported="true"
android:windowSoftInputMode="adjustResize">
上\nclass Bottom2TopRouter extends PageRouteBuilder {\n final Widget child;\n final int duration;\n final Curve curve;\n\n Bottom2TopRouter(\n {this.child, this.duration = 500, this.curve = Curves.fastOutSlowIn})\n : super(\n transitionDuration: Duration(milliseconds: duration),\n pageBuilder: (ctx, a1, a2) {\n return child;\n },\n transitionsBuilder: (\n ctx,\n a1,\n a2,\n Widget child,\n ) => SlideTransition(\n position: Tween(\n begin: Offset(0.0, 1.0),\n end: Offset(0.0, 0.0),\n ).animate(CurvedAnimation(parent: a1, curve: curve)),\n child: child));\n}\n"},{"id":null,"widgetId":174,"name":"PopupMenuDivider基本使用","priority":1,"subtitle":" \n【height】 : 高度 【double】","code":"import 'package:flutter/material.dart';\nimport '../../../dialogs/dialog_about.dart';\nclass CustomPopupMenuDivider extends StatelessWidget {\n final map = {\n \"关于\": Icons.info_outline,\n \"帮助\": Icons.help_outline,\n \"问题反馈\": Icons.add_comment,\n };\n\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Column(\n children: [\n _buildPopupMenuButton(context),\n PopupMenuDivider(),\n ],\n ),\n );\n }\n\n PopupMenuButton _buildPopupMenuButton(BuildContext context) {\n return PopupMenuButton(\n itemBuilder: (context) => [\n ...buildItems().sublist(0, 2),\n PopupMenuDivider(),\n ...buildItems().sublist(2, 3)\n ],\n offset: Offset(0, 50),\n color: Color(0xffF4FFFA),\n elevation: 1,\n shape: RoundedRectangleBorder(\n borderRadius: BorderRadius.only(\n topLeft: Radius.circular(20),\n bottomRight: Radius.circular(20),\n topRight: Radius.circular(5),\n bottomLeft: Radius.circular(5),\n )),\n onSelected: (e) {\n print(e);\n if (e == '关于') {\n DialogAbout.show(context);\n }\n },\n onCanceled: () => print('onCanceled'),\n );\n }\n\n List> buildItems() {\n return map.keys\n .toList()\n .map((e) => PopupMenuItem(\n value: e,\n child: Wrap(\n spacing: 10,\n children: [\n Icon(\n map[e],\n color: Colors.blue,\n ),\n Text(e),\n ],\n )))\n .toList();\n }\n}\n"},{"id":null,"widgetId":195,"name":"CupertinoScrollbar基本使用","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【controller】 : 控制器 【ScrollController】","code":"import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nclass CustomCupertinoScrollbar extends StatelessWidget {\n final data = [\n Colors.purple[50],\n Colors.purple[100],\n Colors.purple[200],\n Colors.purple[300],\n Colors.purple[400],\n Colors.purple[500],\n Colors.purple[600],\n Colors.purple[700],\n Colors.purple[800],\n Colors.purple[900],\n ];\n\n @override\n Widget build(BuildContext context) {\n return Container(\n height: 200,\n child: CupertinoScrollbar(\n child: ListView(\n padding: EdgeInsets.symmetric(horizontal: 5),\n children: data\n .map((color) => Container(\n alignment: Alignment.center,\n width: 100,\n height: 50,\n color: color,\n child: Text(\n colorString(color),\n style: TextStyle(color: Colors.white, shadows: [\n Shadow(\n color: Colors.black,\n offset: Offset(.5, .5),\n blurRadius: 2)\n ]),\n ),\n ))\n .toList(),\n ),\n ),\n );\n }\n\n String colorString(Color color) =>\n \"#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}\";\n}"},{"id":null,"widgetId":172,"name":"FutureBuilder基本使用","priority":1,"subtitle":" \n【builder】 : 子组件 【AsyncWidgetBuilder】\n【initialData】 : 初始数据 【T】\n【future】 : 异步任务 【Future】","code":"import 'package:flutter/material.dart';\nclass CustomFutureBuilder extends StatefulWidget {\n @override\n _CustomFutureBuilderState createState() => _CustomFutureBuilderState();\n}\n\nclass _CustomFutureBuilderState extends State {\n Future _future;\n\n @override\n void initState() {\n _future = loadData();\n super.initState();\n }\n\n @override\n Widget build(BuildContext context) {\n return Container(\n child: FutureBuilder(\n initialData: 'Load',\n future: _future,\n builder: (ctx, snap) {\n if (snap.connectionState == ConnectionState.done) {\n return Text(snap.data);\n }\n if (snap.connectionState == ConnectionState.waiting) {\n return CircularProgressIndicator();\n }\n if (snap.hasError) {\n return Text('Error');\n }\n return Container();\n }),\n );\n }\n\n Future loadData() async {\n await Future.delayed(Duration(seconds: 2));\n return 'LoadeSuccess';\n }\n}\n"},{"id":null,"widgetId":182,"name":"Overlay基本使用","priority":1,"subtitle":" \n Overlay.of(context).insert插入全局组件","code":"import 'package:flutter/material.dart';\nclass CustomOverlay extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Wrap(\n children: [\n Container(\n height: 50,\n child: RawMaterialButton(\n elevation: 2,\n shape: CircleBorder(\n side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),\n ),\n fillColor: Colors.blue,\n splashColor: Colors.orange,\n textStyle: TextStyle(color: Colors.white),\n child: Icon(Icons.add),\n onPressed: ()=>showFloating(context),\n ),\n ),\n Container(\n height: 50,\n child: RawMaterialButton(\n elevation: 2,\n shape: CircleBorder(\n side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),\n ),\n fillColor: Colors.red,\n splashColor: Colors.orange,\n textStyle: TextStyle(color: Colors.white),\n child: Icon(Icons.remove),\n onPressed: hideFloating,\n ),\n ),\n ],\n );\n }\n}\n"},{"id":null,"widgetId":139,"name":"CupertinoPicker基本使用","priority":1,"subtitle":" \n【children】 : 子组件列表 【List】\n【offAxisFraction】 : 轴偏移率 【double】\n【squeeze】 : 挤压率 【double】\n【diameterRatio】 : 高与圆柱直径比率 【double】\n【itemExtent】 : 间距 【double】\n【backgroundColor】 : 背景色 【Color】\n【onSelectedItemChanged】 : 选中事件 【Function(int)】","code":"import 'package:flutter/cupertino.dart';\nclass CustomCupertinoPicker extends StatelessWidget {\n final names = [\n 'Java',\n 'Kotlin',\n 'Dart',\n 'Swift',\n 'C++',\n 'Python',\n \"JavaScript\",\n \"PHP\",\n \"Go\",\n \"Object-c\"\n ];\n\n @override\n Widget build(BuildContext context) {\n return Container(\n height: 150,\n child: CupertinoPicker(\n backgroundColor: CupertinoColors.systemGrey.withAlpha(33),\n diameterRatio: 1,\n offAxisFraction: 0.4,\n squeeze: 1.5,\n itemExtent: 40,\n onSelectedItemChanged: (position) {\n print('当前条目 ${names[position]}');\n },\n children: names.map((e) => Center(child: Text(e))).toList()),\n );\n }\n}\n"},{"id":null,"widgetId":118,"name":"AnimatedOpacity基本使用","priority":1,"subtitle":" \n【child】 : 孩子组件 【Widget】\n【duration】 : 动画时长 【Duration】\n【onEnd】 : 动画结束回调 【Function()】\n【curve】 : 动画曲线 【Duration】\n【opacity】 : 透明度 【double】","code":"import 'package:flutter/material.dart';\nclass CustomAnimatedOpacity extends StatefulWidget {\n @override\n _CustomAnimatedOpacityState createState() => _CustomAnimatedOpacityState();\n}\n\nclass _CustomAnimatedOpacityState extends State {\n double _opacity = 1.0;\n\n @override\n Widget build(BuildContext context) {\n return Column(\n children: [\n Switch(\n value: _opacity == 0,\n onChanged: (v) {\n setState(() {\n _opacity = v ? 0 : 1.0;\n });\n }),\n Container(\n color: Colors.grey.withAlpha(22),\n width: 200,\n height: 100,\n child: AnimatedOpacity(\n duration: Duration(seconds: 1),\n curve: Curves.fastOutSlowIn,\n opacity: _opacity,\n onEnd: () => print('End'),\n child: Icon(Icons.android, color: Colors.green, size: 60),\n ),\n ),\n ],\n );\n }\n}\n"},{"id":null,"widgetId":55,"name":"DropdownButton的样式指定","priority":2,"subtitle":" \n【isDense】 : 是否紧排 【bool】\n【iconSize】 : 图标大小 【double】\n【hint】 : 提示组件 【Widget】\n【iconEnabledColor】 : 图标颜色 【Color】","code":"import 'package:flutter/material.dart';\nclass StyleDropDownButton extends StatefulWidget {\n @override\n _StyleDropDownButtonState createState() => _StyleDropDownButtonState();\n}\n\nclass _StyleDropDownButtonState extends State {\n Color _color = Colors.red ;\n final _colors = [Colors.red, Colors.yellow, Colors.blue, Colors.green];\n final _info = [\"红色\", \"黄色\", \"蓝色\", \"绿色\"];\n\n @override\n Widget build(BuildContext context) {\n return Wrap(\n crossAxisAlignment: WrapCrossAlignment.center,\n children: [\n Container(\n margin: EdgeInsets.symmetric(horizontal: 20),\n width: 50,\n height: 50,\n color: _color??Colors.transparent,\n ),\n DropdownButton(\n hint: Text('请选择'),\n isDense: true,\n iconSize:20,\n iconEnabledColor:_color??Colors.orange,\n value: _color,\n items: _buildItems(),\n onChanged: (v) => setState(() => _color = v)),\n ],\n );\n }\n\n List> _buildItems() => _colors\n .map((e) => DropdownMenuItem(\n value: e,\n child: Text(\n _info[_colors.indexOf(e)],\n style: TextStyle(color: e),\n )))\n .toList();\n}\n"},{"id":null,"widgetId":55,"name":"DropdownButton基本用法","priority":1,"subtitle":" \n【value】 : 当前值 【T】\n【items】 : 下拉选框 【List>】\n【icon】 : 图标 【Widget】\n【elevation】 : 影深 【double】\n【onChanged】 : 选择条目事件 【Function(T)】\n【backgroundColor】 : 背景色 【Color】","code":"import 'package:flutter/material.dart';\nclass CustomDropDownButton extends StatefulWidget {\n @override\n _CustomDropDownButtonState createState() => _CustomDropDownButtonState();\n}\n\nclass _CustomDropDownButtonState extends State {\n Color _color = Colors.red;\n final _colors = [Colors.red, Colors.yellow, Colors.blue, Colors.green];\n final _info = [\"红色\", \"黄色\", \"蓝色\", \"绿色\"];\n\n @override\n Widget build(BuildContext context) {\n return Wrap(\n children: [\n Container(\n margin: EdgeInsets.symmetric(horizontal: 20),\n width: 50,\n height: 50,\n color: _color,\n ),\n DropdownButton(\n value: _color,\n elevation: 1,\n icon: Icon(\n Icons.expand_more,\n size: 20,\n color: _color,\n ),\n items: _buildItems(),\n onChanged: (v) => setState(() => _color = v)),\n ],\n );\n }\n\n List> _buildItems() => _colors\n .map((e) => DropdownMenuItem(\n value: e,\n child: Text(\n _info[_colors.indexOf(e)],\n style: TextStyle(color: e),\n )))\n .toList();\n}"},{"id":null,"widgetId":56,"name":"PopupMenuButton基本使用","priority":1,"subtitle":" \n【itemBuilder】 : 构造器 【PopupMenuItemBuilder】\n【offset】 : 偏移 【Offset】\n【color】 : 背景颜色 【Color】\n【shape】 : 形状 【ShapeBorder】\n【elevation】 : 影深 【double】\n【onCanceled】 : 取消事件 【Function()】\n【onSelected】 : 选择事件 【Function(T)】","code":"import 'package:flutter/material.dart';\nimport '../../../dialogs/dialog_about.dart';\nclass CustomPopupMenuButton extends StatefulWidget {\n @override\n _CustomPopupMenuButtonState createState() => _CustomPopupMenuButtonState();\n}\n\nclass _CustomPopupMenuButtonState extends State {\n final map = {\n \"关于\": Icons.info_outline,\n \"帮助\": Icons.help_outline,\n \"问题反馈\": Icons.add_comment,\n };\n\n @override\n Widget build(BuildContext context) {\n return PopupMenuButton(\n itemBuilder: (context) => buildItems(),\n offset: Offset(0, 50),\n color: Color(0xffF4FFFA),\n elevation: 1,\n shape: RoundedRectangleBorder(\n borderRadius: BorderRadius.only(\n topLeft: Radius.circular(20),\n bottomRight: Radius.circular(20),\n topRight: Radius.circular(5),\n bottomLeft: Radius.circular(5),\n )),\n onSelected: (e) {\n print(e);\n if (e == '关于') {\n DialogAbout.show(context);\n }\n },\n onCanceled: () => print('onCanceled'),\n );\n }\n\n List> buildItems() {\n return map.keys\n .toList()\n .map((e) => PopupMenuItem(\n value: e,\n child: Wrap(\n spacing: 10,\n children: [\n Icon(\n map[e],\n color: Colors.blue,\n ),\n Text(e),\n ],\n )))\n .toList();\n }\n}\n"},{"id":null,"widgetId":160,"name":"Material的shape属性","priority":2,"subtitle":" \n【shape】 : 形状 【ShapeBorder】,","code":"import 'package:flutter/material.dart';\nclass ShapeMaterial extends StatelessWidget {\n\n final shapeMap = {\n 'BorderDirectional': BorderDirectional(\n top: BorderSide(\n color: Colors.white,\n ),\n start: BorderSide(color: Colors.black, width: 15),\n bottom: BorderSide(\n color: Colors.white,\n )),\n 'Border': Border(\n top: BorderSide(width: 5.0, color: Color(0xFFFFDFDFDF)),\n left: BorderSide(width: 5.0, color: Color(0xFFFFDFDFDF)),\n right: BorderSide(width: 5.0, color: Color(0xFFFF7F7F7F)),\n bottom: BorderSide(width: 5.0, color: Color(0xFFFF7F7F7F)),\n ),\n 'Circle': CircleBorder(\n side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)),\n ),\n 'RoundedRectangleBorder': RoundedRectangleBorder(\n side: BorderSide(width: 1.0, color: Colors.black),\n borderRadius: BorderRadius.all(Radius.circular(15))),\n 'ContinuousRectangleBorder': ContinuousRectangleBorder(\n side: BorderSide.none,\n borderRadius: BorderRadius.circular(40.0),\n )\n };\n\n @override\n Widget build(BuildContext context) {\n return Wrap(\n spacing: 10,\n runSpacing: 10,\n children: shapeMap.keys.map((e) => _buildMaterial(e)).toList());\n }\n\n Material _buildMaterial(String type) => Material(\n shadowColor: Colors.blue,\n shape: shapeMap[type],\n color: Colors.orange,\n elevation: 3,\n textStyle: TextStyle(color: Colors.white),\n child: Container(\n alignment: Alignment.center,\n width: 300,\n height: 60,\n child: Text(\n type,\n ),\n ),\n );\n}\n"},{"id":null,"widgetId":160,"name":"Material基本使用","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【type】 : 类型 【MaterialType】\n【elevation】 : 影深 【double】\n【shadowColor】 : 阴影颜色 【Color】\n【color】 : 颜色 【Color】","code":"import 'package:flutter/material.dart';\nclass CustomMaterial extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Wrap(\n spacing: 10,\n runSpacing: 10,\n children: MaterialType.values.map((e) => _buildMaterial(e)).toList());\n }\n\n Material _buildMaterial(MaterialType type) => Material(\n shadowColor: Colors.blue,\n type: type,\n color: Colors.orange,\n elevation: 3,\n child: Container(\n alignment: Alignment.center,\n width: 100,\n height: 60,\n child: Text(\n type.toString().split('.')[1],\n style: TextStyle(color: Colors.black),\n ),\n ),\n );\n}\n"},{"id":null,"widgetId":194,"name":"Scrollbar基本使用","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【controller】 : 控制器 【ScrollController】","code":"import 'package:flutter/material.dart';\nclass CustomScrollbar extends StatelessWidget {\n final data = [\n Colors.purple[50],\n Colors.purple[100],\n Colors.purple[200],\n Colors.purple[300],\n Colors.purple[400],\n Colors.purple[500],\n Colors.purple[600],\n Colors.purple[700],\n Colors.purple[800],\n Colors.purple[900],\n ];\n\n @override\n Widget build(BuildContext context) {\n return Container(\n height: 200,\n child: Scrollbar(\n child: ListView(\n padding: EdgeInsets.symmetric(horizontal: 5),\n children: data\n .map((color) => Container(\n alignment: Alignment.center,\n width: 100,\n height: 50,\n color: color,\n child: Text(\n colorString(color),\n style: TextStyle(color: Colors.white, shadows: [\n Shadow(\n color: Colors.black,\n offset: Offset(.5, .5),\n blurRadius: 2)\n ]),\n ),\n ))\n .toList(),\n ),\n ),\n );\n }\n\n String colorString(Color color) =>\n \"#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}\";\n}"},{"id":null,"widgetId":170,"name":"WillPopScope使用","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【onWillPop】 : 返回回调 【WillPopCallback】","code":"import 'package:flutter/material.dart';\nclass CustomWillPopScope extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: WillPopScope(child: (BackButton()),\n onWillPop: ()=>_willPop(context)),\n );\n }\n\n Future _willPop(context) async{\n return await showDialog(\n context: context,\n builder: (context) => AlertDialog(\n shape: RoundedRectangleBorder(\n borderRadius: BorderRadius.all(Radius.circular(10))),\n title: Text('提示'),\n content: Text('你确定要离开此页吗?'),\n actions: [\n FlatButton(\n onPressed: () => Navigator.of(context).pop(true),\n child: Text('确定'),\n ),\n FlatButton(\n onPressed: () => Navigator.of(context).pop(false),\n child: Text('取消'),\n ),\n\n ],\n ),\n ) ?? false;\n\n }\n}\n"},{"id":null,"widgetId":151,"name":"TableRowInkWell基本事件","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【onTap】 : 点击事件 【Function()】\n【onDoubleTap】 : 双击事件 【Function()】\n【onLongPress】 : 长按事件 【Function()】\n【onHighlightChanged】 : 高亮变化回调 【Function(bool)】","code":"import 'package:flutter/material.dart';\nclass CustomTableRowInkWell extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n var title = _ItemBean(\"单位称\", \"量纲\", \"单位\", \"单位名称\", \"单位符号\");\n var m = _ItemBean(\"长度\", \"L\", \"1m\", \"米\", \"m\");\n var kg = _ItemBean(\"质量\", \"M\", \"1Kg\", \"千克\", \"Kg\");\n var s = _ItemBean(\"时间\", \"T\", \"1s\", \"秒\", \"s\");\n var a = _ItemBean(\"安培\", \"Ι\", \"1A\", \"安培\", \"A\");\n var k = _ItemBean(\"热力学温度\", \"θ\", \"1K\", \"开尔文\", \"K\");\n var mol = _ItemBean(\"物质的量\", \"N\", \"1mol\", \"摩尔\", \"mol\");\n var cd = _ItemBean(\"发光强度\", \"J\", \"1cd\", \"坎德拉\", \"cd\");\n\n var data = <_ItemBean>[title, m, kg, s, a, k, mol, cd];\n\n return SingleChildScrollView(\n scrollDirection: Axis.horizontal,\n child: Table(\n columnWidths: const {\n 0: FixedColumnWidth(80.0),\n 1: FixedColumnWidth(80.0),\n 2: FixedColumnWidth(80.0),\n 3: FixedColumnWidth(80.0),\n 4: FixedColumnWidth(80.0),\n },\n defaultVerticalAlignment: TableCellVerticalAlignment.middle,\n border: TableBorder.all(\n color: Colors.orangeAccent, width: 1.0, style: BorderStyle.solid),\n children: data\n .map((item) => TableRow(children: [\n TableRowInkWell(\n onTap: () => print('onTap'),\n onDoubleTap: () => print('onDoubleTap'),\n onLongPress: () => print('onLongPress'),\n onHighlightChanged: (v) => print('onHighlightChanged:$v'),\n child: Center(\n child: Text(\n item.name,\n style: TextStyle(color: Colors.blue),\n )),\n ),\n Padding(\n padding: const EdgeInsets.all(8.0),\n child: Center(child: Text(item.symbol)),\n ),\n Padding(\n padding: const EdgeInsets.all(8.0),\n child: Center(child: Text(item.unitSymbol)),\n ),\n Padding(\n padding: const EdgeInsets.all(8.0),\n child: Center(child: Text(item.unitName)),\n ),\n Padding(\n padding: const EdgeInsets.all(8.0),\n child: Center(child: Text(item.unit)),\n ),\n ]))\n .toList(),\n ),\n );\n }\n}\n\nclass _ItemBean {\n String name;\n String symbol;\n String unit;\n String unitName;\n String unitSymbol;\n\n _ItemBean(this.name, this.symbol, this.unit, this.unitName, this.unitSymbol);\n}\n\n"},{"id":null,"widgetId":135,"name":"MonthPicker基本使用","priority":1,"subtitle":" \n【selectedDate】 : 选中日期 【DateTime】\n【firstDate】 : 最前日期限制 【DateTime】\n【lastDate】 : 最后日期限制 【DateTime】\n【onChanged】 : 点击回调 【Function(DateTime)】","code":"import 'package:flutter/material.dart';\nclass CustomMonthPicker extends StatefulWidget {\n @override\n _CustomMonthPickerState createState() => _CustomMonthPickerState();\n}\n\nclass _CustomMonthPickerState extends State {\n DateTime _date = DateTime.now();\n\n @override\n Widget build(BuildContext context) {\n return Container(\n height: 350,\n child: MonthPicker(\n selectedDate: _date,\n onChanged: (date) => setState(() => _date = date),\n firstDate: DateTime(2018),\n lastDate: DateTime(2030),\n ),\n );\n }\n}\n"},{"id":null,"widgetId":143,"name":"CupertinoContextMenu基本使用","priority":1,"subtitle":" \n【child】 : 子组件 【Widget】\n【actions】 : 行为组件集 【List】\n【previewBuilder】 : 动画构造器 【ContextMenuPreviewBuilder】","code":"import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nclass CustomCupertinoContextMenu extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: _buildCupertinoContextMenu(context),\n );\n }\n\n final info= ['保存图片','立刻呼叫','添加到收藏夹'];\n\n Widget _buildCupertinoContextMenu(context) => Container(\n decoration: BoxDecoration(\n image: DecorationImage(\n image: AssetImage('assets/images/sabar_bar.jpg'),\n fit: BoxFit.cover),\n borderRadius: BorderRadius.all(Radius.circular(50))),\n width: 100,\n height: 100,\n child: CupertinoContextMenu(\n child: Container(\n decoration: BoxDecoration(\n image: DecorationImage(\n image: AssetImage('assets/images/sabar_bar.jpg'),\n fit: BoxFit.cover),\n borderRadius: BorderRadius.all(Radius.circular(50))),\n ),\n actions: info.map((e)=>CupertinoContextMenuAction(\n child: Center(child: Text(e)),\n onPressed: () => Navigator.pop(context),\n )).toList())\n );\n}\n"}]
\ No newline at end of file
diff --git a/assets/data/web/widget.json b/assets/data/web/widget.json
new file mode 100644
index 00000000..8dd52f79
--- /dev/null
+++ b/assets/data/web/widget.json
@@ -0,0 +1 @@
+[{"id":1,"family":0,"name":"Container","nameCN":"容器组件","lever":5,"linkWidget":"74,85,80,78,70,123","info":"用于容纳单个子组件的容器组件。集成了若干个单子组件的功能,如内外边距、形变、装饰、约束等...","image":"assets/images/widgets/Container.png"},{"id":2,"family":0,"name":"Text","nameCN":"文字组件","lever":5,"linkWidget":"101,324","info":"用于显示文字的组件。拥有的属性非常多,足够满足你的使用需求,核心样式由style属性控制。","image":"assets/images/widgets/Text.png"},{"id":3,"family":0,"name":"Card","nameCN":"卡片组件","lever":3,"linkWidget":"160","info":" 基于Material组件实现,用于将单个组件卡片化。并使其具有投影效果,可加外边距,也可以自定义卡片形状。","image":"assets/images/widgets/Card.png"},{"id":4,"family":0,"name":"FlutterLogo","lever":1,"linkWidget":"","nameCN":"Flutter图标","info":"用于展示Flutter图标组件。可定义颜色、尺寸、展示模式等信息,是一个非常简单的组件。","image":"assets/images/widgets/FlutterLogo.png"},{"id":5,"family":0,"name":"Banner","lever":1,"linkWidget":"","nameCN":"角标组件","info":"用于角标显示的组件。可容纳一个子组件,可选择方位添加角标及信息文字,可设置颜色。","image":"assets/images/widgets/Banner.png"},{"id":6,"family":0,"name":"Icon","lever":2,"linkWidget":"7,30,125","nameCN":"图标组件","info":"用于图标显示的组件。可指定图标资源、大小、颜色。非常简单,但是非常用","image":"assets/images/widgets/Icon.png"},{"id":7,"family":0,"name":"ImageIcon","linkWidget":"6,30,125","nameCN":"容器","lever":1,"info":"用于将一个图片变为纯色的组件。可指定大小、颜色。","image":"assets/images/widgets/ImageIcon.png"},{"id":8,"family":0,"name":"FadeInImage","nameCN":"淡入图片","linkWidget":"38","lever":2,"info":"透明渐变地加载一张图片。可指定占位图片、进退的动画曲线、时间、宽高、fit类型、对齐方式、重复方式等。","image":""},{"id":9,"family":0,"name":"CircleAvatar","nameCN":"圆形组件","linkWidget":"","lever":4,"info":"可将一张图片变成圆形,并且中间可以放置一个组件。可指定半径、前景色、背景色等。","image":""},{"id":10,"family":0,"name":"Visibility","nameCN":"显隐组件","linkWidget":"71","lever":3,"info":"控制一个组件显示或隐藏,可设置隐藏后的占位组件。与其功能相似的由OffStage组件。","image":"assets/images/widgets/Visibility.png"},{"id":11,"family":0,"name":"Chip","nameCN":"小条组件","linkWidget":"12,13,14,15,153","lever":4,"info":"一个横向的圆边小条,可以包含左中右三个组件。可以指定颜色、阴影色和点击事件。","image":"assets/images/widgets/Chip.png"},{"id":12,"family":0,"name":"ChoiceChip","nameCN":"选择小条","lever":3,"linkWidget":"11,13,14,15,153","info":"和Chip组件类似的样式,有一些选择的属性。可以指定选中时的颜色、阴影色和选择事件。","image":"assets/images/widgets/ChoiceChip.png"},{"id":13,"family":0,"name":"ActionChip","nameCN":"事件小条","lever":3,"linkWidget":"11,12,14,15,153","info":"和Chip组件类似的样式,有一些点击的属性。可以指定点击时的阴影深、点击事件。","image":"assets/images/widgets/ActionChip.png"},{"id":14,"family":0,"name":"InputChip","nameCN":"综合小条","linkWidget":"11,12,13,15,153","lever":4,"info":"和Chip组件类似的样式,集成了点击、删除、选择事件为一体。注意:点击事件和选择事件不能同时存在。","image":"assets/images/widgets/InputChip.png"},{"id":15,"family":0,"name":"FilterChip","linkWidget":"11,12,13,14,153","nameCN":"过滤小条","lever":4,"info":"和Chip组件类似的样式,具有选中与否的属性和选中事件。当选中时左侧组件上层会被✔️遮罩。","image":"assets/images/widgets/FilterChip.png"},{"id":16,"family":0,"name":"ListTile","nameCN":"列表瓦片","linkWidget":"162,334","lever":3,"info":"Flutter提供的一个通用列表条目结构,为左中右结构。相应位置可插入组件,可以很方便地应对特定的条目。","image":"assets/images/widgets/ListTile.png"},{"id":17,"family":0,"name":"CheckboxListTile","nameCN":"复选瓦片","linkWidget":"39","lever":3,"info":"Flutter提供的一个通用列表条目结构,为左中结构,尾部是一个CheckBox。相应位置可插入组件,可以很方便地应对特定的条目。","image":"assets/images/widgets/CheckBoxListTile.png"},{"id":18,"family":0,"name":"SwitchListTile","nameCN":"切钮瓦片","linkWidget":"40","lever":3,"info":"Flutter提供的一个通用列表条目结构,为左中结构,尾部是一个Switch。相应位置可插入组件,可以很方便地应对特定的条目。","image":"assets/images/widgets/SwitchListTile.png"},{"id":19,"family":0,"name":"RadioListTile","nameCN":"选钮瓦片","linkWidget":"45","lever":3,"info":"Flutter提供的一个通用列表条目结构,为中右结构,尾部是一个Radio。相应位置可插入组件,可以很方便地应对特定的条目。","image":"assets/images/widgets/RadioListTile.png"},{"id":20,"family":0,"name":"GridTileBar","nameCN":"网格瓦片头","linkWidget":"21","lever":2,"info":"Flutter提供的一个通用头结构,为左中右结构。相应位置可插入组件,可以很方便地应对特定的条目,相比ListTile而言,属性较少。","image":"assets/images/widgets/GridTileBar.png"},{"id":21,"family":0,"name":"GridTile","nameCN":"网格瓦片","linkWidget":"20","lever":3,"info":"Flutter提供的一个通用列表条目结构,可指定头、尾、子组件,常用于网格列表。","image":"assets/images/widgets/GridTile.png"},{"id":22,"family":0,"name":"UserAccountsDrawerHeader","nameCN":"展示头","linkWidget":"154","lever":3.8,"info":"Flutter提供的一个通用展示结构,相应位置可插入组件,可以很方便地应对特定的条目,常用于Drawer中。","image":"assets/images/widgets/UserAccountsDrawerHeader.png"},{"id":23,"family":0,"name":"MaterialButton","nameCN":"材料按钮","linkWidget":"25,26,27,326,175","lever":4,"info":"基于RawMaterialButton实现的通用Material按钮。可盛放一个子组件,能定义颜色、形状等表现,可接收点击和长按事件。","image":""},{"id":24,"family":1,"name":"CupertinoButton","nameCN":"iOS按钮","linkWidget":"23","lever":3,"info":"iOS风格的按钮。可指定颜色、点击时透明度、内边距、圆角等。可接收点击事件。","image":""},{"id":25,"family":0,"name":"FlatButton","nameCN":"平按钮","linkWidget":"24,26,27,175","lever":3,"info":"无阴影的平按钮,基于MaterialButton实现,所有属性和MaterialButton类似。","image":""},{"id":26,"family":0,"name":"RaisedButton","nameCN":"浮起按钮","linkWidget":"24,25,27,175","lever":3,"info":"有阴影的浮起按钮,基于MaterialButton实现,所有属性和MaterialButton类似。","image":""},{"id":27,"family":0,"name":"OutlineButton","nameCN":"线框按钮","linkWidget":"23,24,25,175","lever":3,"info":"边框样式按钮,基于MaterialButton实现,所有属性和MaterialButton类似。","image":""},{"id":28,"family":0,"name":"FloatingActionButton","nameCN":"浮动按钮","linkWidget":"64","lever":4,"info":"浮动按钮,一般用于Scaffold中,可摆放在特定位置。可盛放一个子组件,接收点击、可定义颜色、形状等。","image":""},{"id":29,"family":0,"name":"ButtonBar","nameCN":"按钮栏","linkWidget":"","lever":3,"info":"接收组件列表,常用于盛放若干个按钮。可指定对齐方式、边距等信息。","image":""},{"id":30,"family":0,"name":"IconButton","nameCN":"图标按钮","linkWidget":"6","lever":2,"info":"可点击的图标按钮,可指定图标信息、内边距、大小、颜色等,接收点击事件。","image":""},{"id":31,"family":0,"name":"BackButton","nameCN":"返回按钮","linkWidget":"30","lever":1,"info":"一个具有返回功能的IconButton,返回图标不可更改。在iOS和Android中表现不同","image":""},{"id":32,"family":0,"name":"CloseButton","nameCN":"关闭按钮","linkWidget":"30","lever":1.0,"info":"一个具有关闭功能的IconButton,关闭图标不可更改。","image":""},{"id":33,"family":0,"name":"ToggleButtons","nameCN":"切换按钮组","linkWidget":"332,262","lever":4,"info":"接收组件列表,可指定边线、圆角、颜色等属性。根据具体逻辑,可以实现多个按钮单选或多选的需求。","image":""},{"id":34,"family":0,"name":"Divider","nameCN":"水平分割线","linkWidget":"35,329","lever":2,"info":"水平分割线,可指定颜色、高度、粗细、左右边距信息,常用与列表的item分割线。","image":""},{"id":35,"family":0,"name":"VerticalDivider","nameCN":"竖直分割线","linkWidget":"34,329","lever":2,"info":"竖直分割线,可指定颜色、宽度、粗细、上下边距信息,常用与列表的item分割线。","image":""},{"id":36,"family":0,"name":"Placeholder","nameCN":"占位组件","linkWidget":"","lever":1,"info":"一个矩形和叉叉的占位组件,可指定颜色、线宽、宽高等属性。","image":""},{"id":37,"family":0,"name":"GridPager","nameCN":"网格线组件","linkWidget":"","lever":2,"info":"可容纳一个组件,在其上绘制网格。可指定颜色、线宽、间距等属性。","image":""},{"id":38,"family":1,"name":"Image","nameCN":"图片组件","linkWidget":"8,87","lever":5,"info":"用于显示一张图片,可以从文件、内存、网络、资源里加载。可以指定适应方式、样式、颜色混合模式、重复模式等","image":""},{"id":39,"family":1,"name":"Checkbox","nameCN":"复选框","linkWidget":"17","lever":4,"info":"复选框组件,常用于配置的切换,可指定颜色,接收状态变化回调,也可指定三态。","image":""},{"id":40,"family":1,"name":"Switch","nameCN":"切钮","linkWidget":"41,18","lever":4,"info":"切换选钮,常用于配置的切换,可指定小圆颜色、图片,滑槽颜色等,接收状态变化回调。","image":""},{"id":41,"family":1,"name":"CupertinoSwitch","nameCN":"iOS切钮","linkWidget":"40","lever":3,"info":"iOS风格的切换选钮,常用于配置的切换,可指定颜色,接收状态变化回调。","image":""},{"id":42,"family":1,"name":"Slider","nameCN":"滑块","linkWidget":"43,44,331","lever":4,"info":"滑块组件,可以在指定的最大值和最小值之间拖动选择。可指定颜色、分段数及显示的标签,接收进度变化回调。","image":""},{"id":43,"family":1,"name":"CupertinoSlider","linkWidget":"42","nameCN":"iOS滑块","lever":3,"info":"iOS风格的滑块组件,可以在指定的最大值和最小值之间拖动选择。可指定颜色,接收进度变化回调。","image":""},{"id":44,"family":1,"name":"RangeSlider","nameCN":"范围滑块","linkWidget":"42","lever":4,"info":"范围滑块组件,支持两点拖动,获取之间的范围。可指定颜色、分段数及显示的标签,接收进度变化回调。","image":""},{"id":45,"family":1,"name":"Radio","nameCN":"选钮","linkWidget":"19","lever":4,"info":"由于选中和未选择状态的圆钮,多个Radio根据逻辑可以实现单选或多选的需求。可指定颜色,接收状态变化回调。","image":""},{"id":46,"family":1,"name":"CircularProgressIndicator","nameCN":"圆形进度","linkWidget":"47,48","lever":3,"info":"圆形的进度显示,可指定颜色、线宽、进度等属性。value为null时会不停旋转。","image":""},{"id":47,"family":1,"name":"LinearProgressIndicator","nameCN":"水平进度","linkWidget":"46,48","lever":3,"info":"直线型的进度显示,可指定颜色、进度等属性。value为null时会不停旋转。","image":""},{"id":48,"family":1,"name":"CupertinoActivityIndicator","nameCN":"iOS指示器","linkWidget":"46,47","lever":2,"info":"iOS样式的loading显示组件,可指定半径和是否旋转。","image":""},{"id":49,"family":1,"name":"RefreshIndicator","nameCN":"刷新指示器","linkWidget":"","lever":4,"info":"内部嵌套可滑动区域,下滑时会显示刷新图标,松手后可以执行指定的异步方法。可指定颜色、到顶端距离等属性。","image":""},{"id":50,"family":1,"name":"Tooltip","nameCN":"提示工具","linkWidget":"","lever":3,"info":"由于显示提示信息的组件,长按时显示信息。可指定边距、显示时长、文字样式、装饰灯属性。","image":""},{"id":51,"family":1,"name":"ExpandIcon","nameCN":"展开图标","linkWidget":"66,125","lever":1,"info":"一个展开按钮,点击时会自己执行旋转180的动画。可指定颜色、大小、边距,接收点击事件。","image":""},{"id":52,"family":1,"name":"ExpansionTile","nameCN":"展开瓦片","linkWidget":"178","lever":3,"info":"一个通用的展开栏,可在指定的部位安放组件,点击时会折叠显隐下方组件。接收折叠时事件。","image":""},{"id":53,"family":1,"name":"SelectableText","nameCN":"可选择文字","linkWidget":"2","lever":3,"info":"可选择的文字,可以选择、复制。可指定浮标的颜色、大小、文字样式、对齐方式等。","image":""},{"id":54,"family":1,"name":"TextField","nameCN":"输入框","linkWidget":"199","lever":5,"info":"由于输入的组件,拥有复杂的属性。可指定控制器、文字样式、装饰线、行数限制、游标样式等。接收输入变化、完成输入等事件。","image":""},{"id":55,"family":1,"name":"DropdownButton","nameCN":"下拉按钮","linkWidget":"181","lever":4,"info":"用于下拉选择的按钮,可指定图标、影深、提示等属性,接收选中变化的事件。","image":""},{"id":56,"family":1,"name":"PopupMenuButton","nameCN":"菜单按钮","linkWidget":"174","lever":4,"info":"弹出菜单栏,可指定偏移、颜色、影深、形状等属性。接收item选中的事件和取消选择事件。","image":""},{"id":57,"family":1,"name":"AppBar","nameCN":"应用头栏","linkWidget":"64","lever":4,"info":"一个应用顶部栏的通用结构,可在指定的部位放置相应的组件,常用于Scaffold组件中。","image":""},{"id":58,"family":1,"name":"TabBar","nameCN":"标签栏","linkWidget":"57,59,148","lever":3,"info":"可滑动和点击标签栏,通常用于AppBar的底部,可与TabBarView联用,实现滑页的效果。","image":""},{"id":59,"family":1,"name":"TabBarView","nameCN":"标签页","linkWidget":"58","lever":2,"info":"通常与TabBar联用,实现滑页的效果。一般不单独使用。","image":""},{"id":60,"family":1,"name":"BottomNavigationBar","nameCN":"底部导航","linkWidget":"61","lever":4,"info":"一个底部导航栏,通常用于Scaffold组件的底部,可指定颜色和模式,接受点击回调,可与PageView实现切页效果。","image":""},{"id":61,"family":1,"name":"BottomAppBar","nameCN":"底部导航","linkWidget":"60","lever":4,"info":"一个可凹嵌的底部导航栏,通常用于Scaffold组件的底部,可指定颜色、影深、形状等属性,可与PageView实现切页效果。","image":""},{"id":62,"family":1,"name":"CupertinoNavigationBar","nameCN":"iOS导航","linkWidget":"","lever":3,"info":"一个iOS风格的应用顶部栏的通用结构,可在指定的部位放置相应的组件。可指定背景色、间距、边线等属性。","image":""},{"id":63,"family":1,"name":"CupertinoTabBar","nameCN":"iOS页签","linkWidget":"158","lever":3,"info":"一个iOS风格的TabBar,通常用于CupertinoTabScaffold。可指定颜色、图标大小、边线等数据。接收item的点击事件。","image":""},{"id":64,"family":1,"name":"Scaffold","nameCN":"脚手架","linkWidget":"57,60,61","lever":4,"info":"一个通用app结构,包括上、下、左、右、中、浮动按钮部位,对应位置可盛放组件。","image":""},{"id":65,"family":1,"name":"MaterialApp","nameCN":"Material应用","linkWidget":"64","lever":5,"info":"Material应用的顶级组件,包含路由生成器、主题、语言、主页等属性。","image":""},{"id":66,"family":2,"name":"ClipOval","nameCN":"椭圆裁剪","linkWidget":"67,68,69","lever":3,"info":"可容纳一个子组件,并将其以宽高为长轴和短轴进行椭圆裁切。","image":""},{"id":67,"family":2,"name":"ClipRect","nameCN":"矩形裁剪","linkWidget":"66,68,69","lever":3,"info":"可容纳一个子组件,并将其进行矩形裁切。可借助SizedBox、Align、AspectRadio等限定组件进行定域。","image":""},{"id":68,"family":2,"name":"ClipRRect","nameCN":"圆角矩形裁剪","linkWidget":"66,67,69","lever":3,"info":"可容纳一个子组件,并将其进行圆角矩形裁剪。指定borderRadius作为边角半径。","image":""},{"id":69,"family":2,"name":"ClipPath","nameCN":"路径裁剪","linkWidget":"66,67,68","lever":5,"info":"可容纳一个子组件,并将其按指定路径进行裁剪。可以自定义路径形状,是一个很灵活的裁剪组件。","image":""},{"id":70,"family":2,"name":"DecoratedBox","nameCN":"装饰盒","linkWidget":"1","lever":4,"info":"可容纳一个子组件,可将其进行装饰。核心属性为decoration,可设置边线、渐变、阴影、背景图等。","image":""},{"id":71,"family":2,"name":"Offstage","nameCN":"消失组件","linkWidget":"10","lever":3,"info":"可容纳一个子组件,可更改其的消失与否。offstage属性为true表示隐藏。","image":""},{"id":72,"family":2,"name":"RotatedBox","nameCN":"旋转盒","linkWidget":"90","lever":2,"info":"可容纳一个子组件,将其沿顺时针旋转quarterTurns*90°。","image":""},{"id":73,"family":2,"name":"Opacity","nameCN":"透明化","linkWidget":"89,118","lever":3,"info":"可容纳一个子组件,将其透明度变为opacity值, opacity在0~1之间。","image":""},{"id":74,"family":2,"name":"Padding","nameCN":"边距组件","linkWidget":"1,191","lever":4,"info":"可容纳一个子组件,添加自身内边距来限制孩子组件的占位,核心属性为padding。","image":""},{"id":75,"family":2,"name":"Baseline","nameCN":"基线组件","linkWidget":"2","lever":2,"info":"可容纳一个子组件,通过控制基线高度来控制子组件的位置。一般用于文字组件。","image":""},{"id":76,"family":2,"name":"SizedBox","nameCN":"定尺寸盒","linkWidget":"1","lever":4,"info":"可容纳一个子组件,通过指定宽高限定子组件容身区域。","image":""},{"id":77,"family":2,"name":"AspectRatio","nameCN":"比例盒","linkWidget":"82","lever":3,"info":"可容纳一个子组件,通过指定宽高比aspectRatio,来限定子组件容身区域。","image":""},{"id":78,"family":2,"name":"Transform","nameCN":"变换","linkWidget":"1","lever":4,"info":"可容纳一个子组件,可以通过一个4*4的变换矩阵对子组件进行变换。","image":""},{"id":79,"family":2,"name":"LimitedBox","nameCN":"限制盒","linkWidget":"80","lever":3,"info":"可容纳一个子组件,通过指定最大宽高来限定子组件容身区域。","image":""},{"id":80,"family":2,"name":"ConstrainedBox","nameCN":"约束盒","linkWidget":"1,79,81","lever":3,"info":"可容纳一个子组件,通过指定最大、最小宽高,来限定子组件容身区域。","image":""},{"id":81,"family":2,"name":"UnconstrainedBox","nameCN":"约束盒","linkWidget":"80","lever":3,"info":"可容纳一个子组件,并解除该组件的所有区域约束,展现自我尺寸。","image":""},{"id":82,"family":2,"name":"FractionallySizedBox","nameCN":"分率盒","linkWidget":"77","lever":3,"info":"可容纳一个子组件,指定宽高分率,限定子组件区域为父容器宽高*各分率,及对齐方式alignment。","image":""},{"id":83,"family":2,"name":"OverflowBox","nameCN":"溢出盒","linkWidget":"84","lever":4,"info":"可容纳一个子组件,且子组件允许溢出父组件区域,可以指定宽高的最大最小区域进行限定,拥有对齐属性alignment。","image":""},{"id":84,"family":2,"name":"SizedOverflowBox","nameCN":"尺寸溢出盒","linkWidget":"83","lever":2.8,"info":"可容纳一个子组件,且子组件允许溢出父组件区域,可以通过size属性对子组件进行偏移,拥有对齐属性alignment。","image":""},{"id":85,"family":2,"name":"Align","nameCN":"对齐组件","linkWidget":"1,86,111,120","lever":5,"info":"可容纳一个子组件,可以通过alignment让子组件,定位在父组件宽高的任何指定分率出。","image":""},{"id":86,"family":2,"name":"Center","nameCN":"居中组件","linkWidget":"85","lever":3,"info":"可容纳一个子组件,并使其居中于父组件,是Align组件的一种精简模式。","image":""},{"id":87,"family":2,"name":"FittedBox","nameCN":"适应盒","linkWidget":"38","lever":4,"info":"可容纳一个子组件,使用fit属性决定子组件区域相当于父组件的适应模式,拥有对齐属性alignment。","image":""},{"id":88,"family":2,"name":"ColorFiltered","nameCN":"滤色器","linkWidget":"277,38","lever":5,"info":"可容纳一个子组件,可以并将组件按照29中叠色模式和任意组件混合,强大到我不知道该说什么好。app一键全灰了解一下。","image":""},{"id":89,"family":2,"name":"FadeTransition","nameCN":"透明变换","linkWidget":"73,118","lever":3,"info":"可容纳一个子组件,并使其进行透明度渐变动画,需要提供动画器opacity。","image":""},{"id":90,"family":1,"name":"RotationTransition","nameCN":"旋转变换","linkWidget":"72","lever":3,"info":"可容纳一个子组件,并使其进行旋转动画,需要提供动画器turns,拥有alignment属性。","image":""},{"id":91,"family":1,"name":"ScaleTransition","nameCN":"缩放变换","linkWidget":"","lever":3,"info":"可容纳一个子组件,并使其进行缩放动画,需要提供动画器scale,拥有alignment属性。","image":""},{"id":92,"family":1,"name":"SizeTransition","nameCN":"尺寸变换","linkWidget":"201","lever":3,"info":"可容纳一个子组件,并使其进行尺寸动画,需要提供动画器sizeFactor,可指定尺寸变化轴及轴向的axisAlignment。","image":""},{"id":93,"family":1,"name":"PositionedTransition","nameCN":"位置变换","linkWidget":"97","lever":3,"info":"只能用于Stack中,可容纳一个子组件,让其在两个矩形间进行位置动画,需要提供动画器rect。","image":""},{"id":94,"family":3,"name":"Flex","nameCN":"弹性布局","linkWidget":"95,96,106,107,109","lever":5,"info":"Row和Column的父类,Flutter中最强大的布局方式。可容纳多个组件,可与Spacer、Expended、Flexible组件联用进行灵活布局","image":""},{"id":95,"family":3,"name":"Row","nameCN":"行布局","linkWidget":"94,96","lever":4,"info":"排布方向为横向的Flex布局,可容纳多个组件。其他属性全部一致,详见Flex。","image":""},{"id":96,"family":3,"name":"Column","nameCN":"列布局","linkWidget":"94,95","lever":4,"info":"排布方向为竖向的Flex布局,可容纳多个组件。其他属性全部一致,详见Flex。","image":""},{"id":97,"family":3,"name":"Stack","nameCN":"堆叠布局","linkWidget":"94,95,161","lever":5,"info":"可容纳多个组件,以堆叠的方式摆放子组件,后者居上。拥有alignment属性,可与Positioned组件联合使用,精确定位。","image":""},{"id":98,"family":3,"name":"Wrap","nameCN":"包裹布局","linkWidget":"94,95","lever":5,"info":"可容纳多个组件,按照指定方向依次排布,可以很方便处理孩子的间距,当越界时可以自动换行。拥有主轴和交叉轴的对齐方式,比较灵活。","image":""},{"id":99,"family":3,"name":"Flow","nameCN":"流动布局","linkWidget":"98,94","lever":5,"info":"可容纳多个组件, 需要自己制定排布的代理,可以高强度自定义组件的排布,实现普通布局无法达到的效果。布局王者,当之无愧。","image":""},{"id":100,"family":1,"name":"AnimatedCrossFade","nameCN":"组件切换","linkWidget":"116","lever":5,"info":"将两个组件切换时呈现动画效果,可指定动画曲线、时长、对齐方式等属性。是一个非常有用的组件。","image":""},{"id":101,"family":3,"name":"RichText","nameCN":"富文本","linkWidget":"2","lever":5,"info":"可以容纳多种文字样式或各种组件的富文本组件,应用较为广泛。","image":""},{"id":102,"family":0,"name":"DataTable","nameCN":"数据表格","linkWidget":"110","lever":3,"info":"一个表格组件,可以制订逻辑进行点击、修改、排序等操作。","image":""},{"id":103,"family":1,"name":"Draggable","nameCN":"可拖拽组件","linkWidget":"104,105","lever":4,"info":"可以让组件在界面上任意拖拽,可存放一个泛型T的数据。通常和DragTarget组合使用,来完成拖拽效果。","image":""},{"id":104,"family":1,"name":"DragTarget","nameCN":"拖拽目标","linkWidget":"103,105","lever":4,"info":"一个拖拽的目标区域,可接收Draggable组件的信息。可以获取拖拽时的回调。","image":""},{"id":105,"family":1,"name":"LongPressDraggable","nameCN":"拖拽目标","linkWidget":"103,104","lever":4,"info":"长按时让组件在界面上任意拖拽,可存放一个泛型T的数据。通常和DragTarget组合使用,来完成拖拽效果。","image":""},{"id":106,"family":5,"name":"Expanded","nameCN":"延展组件","linkWidget":"94,109","lever":4,"info":"父类是Flexible,相当于一个fit类型为tight的Flexible组件。可嵌套孩子利用剩余空间对占位空间进行延展。","image":""},{"id":107,"family":0,"name":"Spacer","nameCN":"空间组件","linkWidget":"94","lever":3,"info":"只能用于Row、Column和Flex布局中,可利用剩余空间进行占位,使用flex属性可以给多个Spacer按比例分配空间。","image":""},{"id":108,"family":5,"name":"Positioned","nameCN":"定位组件","linkWidget":"97,159,121","lever":3,"info":"只能用于Stack中,可以指定左上右下的距离对某个组件进行位置精确安放。","image":""},{"id":109,"family":5,"name":"Flexible","nameCN":"灵活组件","linkWidget":"94,106","lever":3,"info":"只能用于只能用于Row、Column和Flex布局中,可嵌套孩子利用剩余空间对占位空间进行延展,也可指定适应类型。","image":""},{"id":110,"family":6,"name":"Table","nameCN":"表格组件","linkWidget":"102","lever":4,"info":"用于展示表格的组件,可指定边线、列宽、文字方向等属性,核心对象类型是TableRow。","image":""},{"id":111,"family":1,"name":"AlignTransition","nameCN":"对齐变换","linkWidget":"85,120","lever":3,"info":"AnimatedWidget的子类,使用Alignment类型的动画器让子组件在两个Alignment对象之间进行过渡动画。","image":""},{"id":112,"family":1,"name":"SlideTransition","nameCN":"滑动变换","linkWidget":"","lever":3,"info":"AnimatedWidget的子类,使用Offset类型的动画器让子组件在两个Offset对象之间进行过渡动画。","image":""},{"id":113,"family":1,"name":"DecoratedBoxTransition","nameCN":"装饰变换","linkWidget":"70","lever":3,"info":"AnimatedWidget的子类,使用Decorated类型的动画器让子组件在两个Decorated对象之间进行过渡动画。","image":""},{"id":114,"family":1,"name":"DefaultTextStyleTransition","nameCN":"文字样式变换","linkWidget":"124,324","lever":3,"info":"AnimatedWidget的子类,使用TextStyle类型的动画器让文字组件在两个TextStyle对象之间进行过渡动画。","image":""},{"id":115,"family":1,"name":"RelativePositionedTransition","nameCN":"矩形位置变换","linkWidget":"70","lever":3,"info":"AnimatedWidget的子类,使用Rect类型的动画器让子组件在两个Rect对象之间进行过渡动画。","image":""},{"id":116,"family":1,"name":"AnimatedSwitcher","nameCN":"动画切换","linkWidget":"100","lever":4,"info":"当子组件变化时执行动画,需要指定子组件的key进行标识。动画方式可以自定义,能指定动画时长、动画曲线等属性。","image":""},{"id":117,"family":1,"name":"AnimatedList","nameCN":"动画列表","linkWidget":"162","lever":3,"info":"强化版的ListView,可以对item进行动画处理。比如在添加、删除是item的动画。","image":""},{"id":118,"family":1,"name":"AnimatedOpacity","nameCN":"透明动画","linkWidget":"89,73","lever":3,"info":"能让子组件进行Opacity(透明度)动画,可指定时长和曲线,有动画结束事件。","image":""},{"id":119,"family":1,"name":"AnimatedPadding","nameCN":"边距动画","linkWidget":"74","lever":3,"info":"能让子组件进行Padding(内边距)动画,可指定时长和曲线,有动画结束事件。","image":""},{"id":120,"family":1,"name":"AnimatedAlign","nameCN":"对齐动画","linkWidget":"85,111","lever":3,"info":"能让子组件进行Align(对齐)动画,可指定时长和曲线,有动画结束事件。","image":""},{"id":121,"family":1,"name":"AnimatedPositioned","nameCN":"定位动画","linkWidget":"108,93,122","lever":3,"info":"能让子组件进行Positioned(定位)动画,可指定时长和曲线,有动画结束事件。只能用于Stack之中。","image":""},{"id":122,"family":1,"name":"AnimatedPositionedDirectional","nameCN":"方向定位动画","linkWidget":"121,159","lever":3,"info":"能让子组件进行PositionedDirectional(方向定位)动画,可指定时长和曲线,有动画结束事件。只能用于Stack之中。","image":""},{"id":123,"family":1,"name":"AnimatedContainer","nameCN":"容器动画","linkWidget":"1","lever":5,"info":"集合alignment、padding、color、decoration、width、height、constraints、margin、transform于一身,这些属性皆可动画,可指定时长和曲线,有动画结束事件。","image":""},{"id":124,"family":1,"name":"AnimatedDefaultTextStyle","nameCN":"容器动画","linkWidget":"114,324","lever":3,"info":"能让子文字组件进行TextStyle(文字样式)动画,可指定时长和曲线,有动画结束事件。","image":""},{"id":125,"family":0,"name":"AnimatedIcon","nameCN":"图标动画","linkWidget":"6","lever":3,"info":"使用AnimatedIcons的图标数据,可以根据一个动画控制器来使图标进行动画效果。可指定图标大小、颜色等。","image":""},{"id":126,"family":0,"name":"Dialog","nameCN":"对话框","linkWidget":"","lever":2,"info":"最简易的对话框面板,包含一个内容组件,可指定影深、背景色、形状等属性。","image":""},{"id":127,"family":0,"name":"AlertDialog","nameCN":"弹出对话框","linkWidget":"129","lever":3,"info":"一个通用的对话框结构,可指定头、中、尾处的组件。拥有标题、内容的文字样式和边距,影深、形状等属性。","image":""},{"id":128,"family":0,"name":"SimpleDialog","nameCN":"简单对话框","linkWidget":"133","lever":3,"info":"一个简单的对话框结构,可指定头、中处的组件。拥有拥有标题、内容的文字样式和边距,影深、形状等属性。常与SimpleDialogOption联用。","image":""},{"id":129,"family":0,"name":"CupertinoAlertDialog","nameCN":"iOS对话框","linkWidget":"127","lever":3,"info":"iOS风格的通用的对话框结构,可指定头、中、尾处的组件。","image":""},{"id":130,"family":0,"name":"AboutDialog","nameCN":"弹出对话框","linkWidget":"193","lever":1,"info":"应用的简介对话框,可指定应用图标、应用名、应用版本号等信息和内部的子组件列表,点击左侧按钮可以跳转到证书页。","image":""},{"id":131,"family":0,"name":"CupertinoActionSheet","nameCN":"iOS行为单","linkWidget":"132","lever":3,"info":"iOS风格的弹出选择结构,可放多的按钮,一般与CupertinoActionSheetAction联用。","image":""},{"id":132,"family":0,"name":"CupertinoActionSheetAction","nameCN":"iOS行为单按键","linkWidget":"131","lever":1,"info":"一个按钮,应用场景很少,通常用于CupertinoActionSheet中,接收点击事件。","image":""},{"id":133,"family":0,"name":"SimpleDialogOption","nameCN":"简单对话框选项","linkWidget":"128","lever":1,"info":"一个按钮,应用场景很少,通常用于SimpleDialog中,接收点击事件。","image":""},{"id":134,"family":0,"name":"DayPicker","nameCN":"日期选择器","linkWidget":"135,136","lever":3,"info":"日期的选择组件,可指定当前日期、选中日期、展示月份等,接收日期选中事件。","image":""},{"id":135,"family":1,"name":"MonthPicker","nameCN":"月份选择器","linkWidget":"134,136","lever":3,"info":"月份的选择组件,自带上下月切换的监听。可指定选择的日期范围、选中日期等,接收日期选中事件。","image":""},{"id":136,"family":1,"name":"YearPicker","nameCN":"年份选择器","linkWidget":"134,135","lever":3,"info":"年份的选择组件,长相比较寒酸。可指定选择的日期范围、选中日期等,接收每份选中事件","image":""},{"id":137,"family":1,"name":"CupertinoDatePicker","nameCN":"iOS日期选择器","linkWidget":"138","lever":3,"info":"高大上的滑滚日期选择器,可指定选择的类型、日期范围等,接收日期选中事件。","image":""},{"id":138,"family":1,"name":"CupertinoTimerPicker","nameCN":"iOS时间选择器","linkWidget":"137","lever":3,"info":"高大上的滑滚时间选择器,可指定选择的类型、初始时间、背景色等,接收时间选中事件。","image":""},{"id":139,"family":1,"name":"CupertinoPicker","nameCN":"iOS选择器","linkWidget":"179","lever":3,"info":"高大上的柱面滑动选择器,精妙十足,可指定很多配置属性,接收滑动时选中事件。","image":""},{"id":140,"family":1,"name":"SnackBar","nameCN":"信息提示条","linkWidget":"141,142","lever":4,"info":"作为组件来说是一个简单的结构组件,可指定形状、影深、背景色等。一般通过ScaffoldState的showSnackBar方法从底部弹出。","image":""},{"id":141,"family":1,"name":"SnackBarAction","nameCN":"信息提示条按钮","linkWidget":"140","lever":1,"info":"一般只用于SnackBar中,接受点击事件。点击一次后该按钮就会被禁用,可以指定颜色和禁用时颜色。","image":""},{"id":142,"family":1,"name":"BottomSheet","nameCN":"底部抽屉","linkWidget":"140","lever":4,"info":"作为组件来说是一个简单的结构组件,可指定形状、影深、背景色、内部组件构造器等。一般通过ScaffoldState的showBottomSheet方法从底部弹出。","image":""},{"id":143,"family":1,"name":"CupertinoContextMenu","nameCN":"ios弹出菜单","linkWidget":"144","lever":5,"info":"一个华丽的iOS风格按钮弹出框,长按时会以动画的形式弹出菜单面板,通常和CupertinoContextMenuAction联用。","image":""},{"id":144,"family":1,"name":"CupertinoContextMenuAction","nameCN":"ios弹出菜单按钮","linkWidget":"143","lever":1,"info":"一般只用于CupertinoContextMenu中的点击按钮。可指定孩子和尾部图标,接收点击事件。","image":""},{"id":145,"family":1,"name":"LicensePage","nameCN":"证书页","linkWidget":"130,193","lever":1,"info":"应用的证书页,可指定应用图标、应用名、应用版本号等信息,其他由Flutter自动生成。","image":""},{"id":146,"family":0,"name":"GestureDetector","nameCN":"手势监听器","linkWidget":"147,150","lever":5,"info":"组件手势事件的检测器,可接受点击、长按、双击,按下、松开、移动等事件,并可以获取触点信息,居家旅行必备组件。","image":""},{"id":147,"family":0,"name":"Listener","nameCN":"事件监听器","linkWidget":"146","lever":3,"info":"组件事件的监听器,可接受按下、松开、移动、取消等事件。较GestureDetector比较原始,可获取的信息也更多。","image":""},{"id":148,"family":0,"name":"Tab","nameCN":"标签","linkWidget":"58","lever":1,"info":"一般用于TabBar中的item,上下结构,可指定图标和一个内容组件。","image":""},{"id":149,"family":1,"name":"InkResponse","nameCN":"水波纹响应","linkWidget":"150,152","lever":1,"info":"水波纹的点击效果,接收点击、双击、长按、取消、高亮变化事件,可指定水波纹颜色、半径、高亮形状等属性。","image":""},{"id":150,"family":1,"name":"InkWell","nameCN":"水波纹","linkWidget":"149,152","lever":4,"info":"InkResponse的子类,基本属性同InkResponse。一个矩形区域的水波纹,可以知道圆角半径,边线形状等。","image":""},{"id":151,"family":1,"name":"TableRowInkWell","nameCN":"表格水波纹","linkWidget":"110","lever":1,"info":"只能用于Table的水波纹,接收点击、双击、长按、高亮变化事件,水波纹会作用于表格的一行。","image":""},{"id":152,"family":1,"name":"Ink","nameCN":"水波","linkWidget":"149,150","lever":3,"info":"使InkWell和InkResponse的水波纹有效,用于绘制图像或其他装饰的Material组件。","image":""},{"id":153,"family":1,"name":"RawChip","nameCN":"原生小条","linkWidget":"11,12,13,14,15","lever":5,"info":"各自Chip组件的始祖,拥有各自Chip表现的能力,支持选中、点击、删除等事件。详见Chip、FilterChip、ActionChip、InputChip、ChoiceChip。","image":""},{"id":154,"family":0,"name":"Drawer","nameCN":"滑页栏","linkWidget":"64,155","lever":2,"info":"一般用于Scaffold中的draw和endDraw属性作为左右的滑页栏,可以容纳一个子组件,能指定影深。","image":""},{"id":155,"family":0,"name":"DrawerHeader","nameCN":"滑页栏","linkWidget":"154","lever":2,"info":"一般用于Drawer中,作为滑页栏的头部。可以指定内外边距、装饰、子组件等属性。","image":""},{"id":156,"family":1,"name":"CupertinoApp","nameCN":"iOS应用","linkWidget":"157,158","lever":4,"info":"iOS风格应用的顶级组件,包含路由生成器、主题、语言、主页等属性。","image":""},{"id":157,"family":1,"name":"CupertinoPageScaffold","nameCN":"iOS页面脚手架","linkWidget":"62","lever":3,"info":"iOS风格的页面布局脚手架结构,可指定顶部的导航栏和页面背景色。","image":""},{"id":158,"family":1,"name":"CupertinoTabScaffold","nameCN":"iOS页签脚手架","linkWidget":"63","lever":3,"info":"iOS风格的页面布局脚手架结构,可指定最底部的导航切换栏可主体内容页。","image":""},{"id":159,"family":0,"name":"PositionedDirectional","nameCN":"方向定位","linkWidget":"108,122","lever":3,"info":"和Positioned组件功能一样,属性名不同。只能用于Stack中,可以指定左上右下的距离对某个组件进行位置精确安放。","image":""},{"id":160,"family":1,"name":"Material","nameCN":"材料组件","linkWidget":"3","lever":5,"info":"Material风格组件的领军人物,灵魂核心。可指定颜色、影深、类型、阴影颜色、形状等属性。","image":""},{"id":161,"family":3,"name":"IndexedStack","nameCN":"索引堆叠","linkWidget":"97","lever":4,"info":"Stack组件的子类,可以堆叠多个组件,并通过index来指定展示的组件索引,其余的会被隐藏。","image":""},{"id":162,"family":0,"name":"ListView","nameCN":"列表组件","linkWidget":"16,163","lever":5,"info":"列表显示的领军人物,容纳多个子组件,可以通过builder、separated、custom等构造。有内边距、是否反向、滑动控制器等属性。","image":""},{"id":163,"family":0,"name":"GridView","nameCN":"网格组件","linkWidget":"21,162","lever":5,"info":"容纳多个组件,并以网格的方式。可以通过count、extent、custom、builder等构造。有内边距、是否反向、滑动控制器等属性。","image":""},{"id":164,"family":0,"name":"SingleChildScrollView","nameCN":"单子滑动","linkWidget":"","lever":5,"info":"使一个组件具有滑动的效果,可指定滑动的方向、是否反向、滑动控制器等属性。","image":""},{"id":165,"family":0,"name":"PageView","nameCN":"滑页","linkWidget":"","lever":5,"info":"容纳多个组件页面,可对它们进行滑动切换,可指定滑动的方向、是否反向、滑动控制器等属性。","image":""},{"id":166,"family":2,"name":"CustomPaint","nameCN":"绘制组件","linkWidget":"","lever":5,"info":"通过CustomPainter进行绘制,可实现一些复杂的自定义绘制组件,是Flutter中自定义组件的灵魂人物。","image":""},{"id":167,"family":5,"name":"MediaQuery","nameCN":"媒体查询","linkWidget":"","lever":4,"info":"可通过MediaQuery.of来获取屏幕尺寸、设备密度、文字缩放比例、边距等信息。","image":""},{"id":168,"family":0,"name":"Theme","nameCN":"主题","linkWidget":"65,169","lever":4,"info":"可通过Theme.of获取ThemeData对象。也可以指定主题应用于Theme的后代组件。","image":""},{"id":169,"family":0,"name":"CupertinoTheme","nameCN":"iOS主题","linkWidget":"156,168","lever":3,"info":"可通过CupertinoTheme.of获取CupertinoThemeData对象。也可以指定主题应用于CupertinoTheme的后代组件。","image":""},{"id":170,"family":1,"name":"WillPopScope","nameCN":"返回拦截","linkWidget":"","lever":5,"info":"当一个界面中有WillPopScope组件时,在页面返回时会触发回调,决定是否返回。可用于二次确认退出的场景。","image":""},{"id":171,"family":1,"name":"Hero","nameCN":"共享动画","linkWidget":"28","lever":5,"info":"可指定标签名,两个界面跳转时具有相同标签的组件会进行共享动画。一个界面中不能存在两个同名的Hero标签","image":""},{"id":172,"family":1,"name":"FutureBuilder","nameCN":"异步构造器","linkWidget":"173","lever":5,"info":"可指定一个Future对象,能够监听异步执行的状态,并在构造器中根据状态构建不同的界面。注意该Future对象不能和FutureBuilder同时创建,否则可能过渡刷新。","image":""},{"id":173,"family":1,"name":"StreamBuilder","nameCN":"流构造器","linkWidget":"172","lever":5,"info":"可指定一个stream对象,能够监听异步执行的状态,并在构造器中根据状态构建不同的界面。","image":""},{"id":174,"family":1,"name":"PopupMenuDivider","nameCN":"弹出菜单分割线","linkWidget":"56,34","lever":1,"info":"PopupMenuButton的分割线,一般不单独使用,可指定高度。","image":""},{"id":175,"family":1,"name":"RawMaterialButton","nameCN":"原始按钮","linkWidget":"23,25,26,27","lever":5,"info":"原始的Material按钮,按钮界的幕后大佬,可接受点击、长按、高亮变化事件,可指定颜色、形状。影深、内边距等属性。","image":""},{"id":176,"family":1,"name":"Dismissible","nameCN":"滑动消失","linkWidget":"162","lever":4,"info":"滑动时可显示底部组件,可指定滑动的方向和交叉轴的偏移量。接收确认消失和消失时的回调。","image":""},{"id":177,"family":1,"name":"ReorderableListView","nameCN":"可重排序列表","linkWidget":"162","lever":4,"info":"可以进行长按排序的ListView,可指定滑动方向、是否反向、滑动控制器等属性。","image":""},{"id":178,"family":1,"name":"ExpansionPanelList","nameCN":"展开列表","linkWidget":"52","lever":3,"info":"可展开的列表组件,可根据逻辑来实现单展开或多展开。可指定展开动画时长,接收展开回调","image":""},{"id":179,"family":1,"name":"ListWheelScrollView","nameCN":"滚轮列表","linkWidget":"139","lever":4,"info":"高大上的柱面滑动列表,精妙十足,可指定item高度、透视、挤压等属性,接收滑动时选中事件。","image":""},{"id":180,"family":5,"name":"ScrollConfiguration","nameCN":"ios菜单按钮","linkWidget":"162,163,164","lever":3,"info":"需要包裹一个可滑动的组件,并通过behavior属性控制滑动的效果,可以去除滑动的蓝色阴影等。","image":""},{"id":181,"family":5,"name":"DropdownButtonHideUnderline","nameCN":"下拉按钮隐藏线","linkWidget":"55","lever":1,"info":"用于去除DropdownButton的下划线,本身没有什么应用价值。","image":""},{"id":182,"family":1,"name":"Overlay","nameCN":"悬浮组件","linkWidget":"","lever":5,"info":"可以将组件在全应用中进行悬浮显示,能够添加或移除组件,它们有独立管理的栈。","image":""},{"id":183,"family":4,"name":"CustomScrollView","nameCN":"通用滑动视图","linkWidget":"184,185,188","lever":5,"info":"一个通用的滑动结构,可以指定滑动方向、是否反向、滑动控制器等属性。其中包含的子组件们必须是Sliver家族。","image":""},{"id":184,"family":4,"name":"SliverAppBar","nameCN":"Sliver头部栏","linkWidget":"183,196","lever":4,"info":"Sliver家族的顶部栏通用结构,可以指定左中右组件、收缩空间、影深、固定模式、背景色等属性。","image":""},{"id":185,"family":4,"name":"SliverList","nameCN":"Sliver列表","linkWidget":"183,186,187","lever":5,"info":"Sliver家族的列表组件,通过指定delegate构造子组件。通常用于CustomScrollView中。","image":""},{"id":186,"family":4,"name":"SliverFixedExtentList","nameCN":"Sliver固定延展列表","linkWidget":"183,185,187","lever":3,"info":"Sliver家族的列表组件,通过delegate构造子组件,可以指定item的高度。通常用于CustomScrollView中。","image":""},{"id":187,"family":4,"name":"SliverFillViewport","nameCN":"Sliver填充视图列表","linkWidget":"183,185,186","lever":3,"info":"Sliver家族的列表组件,通过delegate构造子组件,item的高度会填空视口,可以指定是否的分率。","image":""},{"id":188,"family":4,"name":"SliverGird","nameCN":"Sliver网格","linkWidget":"183","lever":4,"info":"Sliver家族的网格列表组件,和GirdView类似,通过count和extent构造。通常用于CustomScrollView中。","image":""},{"id":189,"family":4,"name":"SliverToBoxAdapter","nameCN":"Sliver适配器","linkWidget":"183","lever":4,"info":"可以容纳一个普通的组件,并将其转化成Sliver家族组件的适配器。","image":""},{"id":190,"family":4,"name":"SliverPersistentHeader","nameCN":"Sliver存留头","linkWidget":"183","lever":5,"info":"通常用于CustomScrollView中,可以让一个组件在滑动中停留在顶部,不会滑动消失。","image":""},{"id":191,"family":4,"name":"SliverPadding","nameCN":"Sliver内间距","linkWidget":"74","lever":3,"info":"可容纳一个Sliver家族的子组件,添加自身内边距来限制孩子组件的占位,核心属性为padding。","image":""},{"id":192,"family":4,"name":"SliverOpacity","nameCN":"Sliver透明度","linkWidget":"73","lever":3,"info":"可容纳一个Sliver家族的子组件,并通过opacity来指定子组件的透明度。","image":""},{"id":193,"family":0,"name":"AboutListTile","nameCN":"关于应用条目","linkWidget":"130,145","lever":3,"info":"一个点击条目,点击时可以弹出应用相关信息,可指定应用图标、应用名、应用版本号等信息和内部的子组件列表。","image":""},{"id":194,"family":1,"name":"Scrollbar","nameCN":"滑动指示栏","linkWidget":"195,164,162","lever":3,"info":"需要包裹一个可滑动区域,当可滑动时,会显示滑动的bar用于指示。","image":""},{"id":195,"family":1,"name":"CupertinoScrollbar","nameCN":"iOS滑动指示栏","linkWidget":"194,164,162","lever":3,"info":"iOS风格的滑动指示栏,需要包裹一个可滑动区域,当可滑动时,会显示滑动的bar用于指示。","image":""},{"id":196,"family":4,"name":"FlexibleSpaceBar","nameCN":"ios菜单按钮","linkWidget":"184","lever":3,"info":"通常用于SliverAppBar中的可伸展区域,可指定标题、标题间距、背景、折叠模式等。","image":""},{"id":197,"family":6,"name":"ErrorWidget","nameCN":"错误组件","linkWidget":"","lever":1,"info":"用于显示一个错误信息的组件,红底黄字,在开发过程中经常看到,一般不使用。","image":""},{"id":198,"family":1,"name":"Form","nameCN":"表单组件","linkWidget":"199","lever":4,"info":"表单组件,可以接收其下的FormField组件的变化回调,通过onWillPop拦截页面返回,通过FormState可对表单字段进行保存或校验。","image":""},{"id":199,"family":1,"name":"TextFormField","nameCN":"文字表单输入","linkWidget":"54,198","lever":4,"info":"和TextField属性基本一致,在其基础上增加字段的校验和提交的回调,FormState的save会触发onSaved回调。","image":""},{"id":200,"family":1,"name":"Stepper","nameCN":"步骤组件","linkWidget":"","lever":5,"info":"步骤组件,可指定一步步的操作,可以自定义步骤的内容,确认和返回的按钮以及步骤排列的方向。","image":""},{"id":201,"family":1,"name":"AnimatedSize","nameCN":"尺寸动画","linkWidget":"92","lever":3,"info":"子组件大小发生变化是,进行动画渐变,可指定时长、对齐方式、曲线、vsync等属性。","image":""},{"id":202,"family":0,"name":"Builder","nameCN":"构造器","linkWidget":"","lever":2,"info":"一个不影响子组件占位空间,不具有显示性的组件,存在的唯一价值是提供当前组件对应元素的上下文。","image":""},{"id":203,"family":0,"name":"OrientationBuilder","nameCN":"方向构造器","linkWidget":"202","lever":2,"info":"能够回调父组件是横向还是纵向,可以据此来构建不同的子组件。","image":""},{"id":204,"family":0,"name":"PreferredSize","nameCN":"优先尺寸","linkWidget":"57,64","lever":2,"info":"实现了PreferredSizeWidget接口,可容纳一个子组件,设置优先尺寸,不会对其子组件施加任何约束。","image":""},{"id":205,"family":0,"name":"TabPageSelector","nameCN":"页签滑动选择器","linkWidget":"206,59","lever":2,"info":"通常作为指示器与TabBarView联用,共同使用一个TabController。可指定颜色、大小、选中色。","image":""},{"id":206,"family":0,"name":"TabPageSelectorIndicator","nameCN":"页签指示器","linkWidget":"205","lever":2,"info":"一个有边线的圆形组件,可指定大小、颜色、边线色。是TabPageSelector的部分之一,一般不单独使用。","image":""},{"id":208,"family":0,"name":"Title","nameCN":"应用标题","linkWidget":"65","lever":2,"info":"该组件用于描述app在操作系统中的名称,可以在应用栏列表里看到效果。MaterialApp中的title字段效果的根源是该组件。","image":""},{"id":211,"family":0,"name":"MaterialBanner","nameCN":"横幅组件","linkWidget":"","lever":2,"info":"Material风格的横幅组件,支持左中右或左中下结构,可指定边距背景色等","image":""},{"id":214,"family":0,"name":"NavigationToolbar","nameCN":"导航工具条","linkWidget":"57","lever":2,"info":"左中右模式的通用结构组件,可指定中间组件距左侧边距及是否居中。源码在AppBar等导航条结构中有使用它。","image":""},{"id":218,"family":0,"name":"CupertinoNavigationBarBackButton","nameCN":"iOS风格返回按钮","linkWidget":"57","lever":2,"info":"Cupertino风格的导航栏返回按钮,可指定颜色和点击事件,一般不单独使用。","image":""},{"id":231,"family":1,"name":"InputDecorator","nameCN":"输入装饰","linkWidget":"54","lever":2,"info":"在外层包裹输入的装饰,是TextField的底层核心组件之一,一般不单独使用。","image":""},{"id":232,"family":1,"name":"Navigator","nameCN":"导航器","linkWidget":"65","lever":4,"info":"Navigator用堆栈规则管理一组子组件,可以将子组件切入弹出及监听出入栈事件。MaterialApp路由管理的本源就是使用了Navigator。","image":""},{"id":244,"family":1,"name":"EditableText","nameCN":"可编辑文字","linkWidget":"2,54","lever":2,"info":"可以编辑的文字,是TextField的底层最核心组件,一般不单独使用。","image":""},{"id":245,"family":1,"name":"CupertinoTextField","nameCN":"iOS风格输入框","linkWidget":"54","lever":4,"info":"Cupertino风格的输入框,属性和TextField类似,可指定控制器、文字样式、装饰线、行数限制、游标样式等。接收输入变化、完成输入等事件。","image":""},{"id":251,"family":4,"name":"NestedScrollView","nameCN":"嵌套滑动视图","linkWidget":"183","lever":4,"info":"用于多个视图滑动嵌套处理,可以指定头部、滑动控制器、滑动方向等,其中body必须是可滑动类型的组件。","image":""},{"id":253,"family":1,"name":"Scrollable","nameCN":"可滑动组件","linkWidget":"340,349","lever":4,"info":"实现了一个可滚动组件的交互模型,需要viewportBuilder进的viewport的构造。是ScrollView的核心实现组件之一,一般不直接使用。","image":""},{"id":255,"family":1,"name":"ValueListenableBuilder","nameCN":"监听值构造器","linkWidget":"","lever":5,"info":"可以监听一个值,当其变化时通过builder回调能重建界面,避免使用setState刷新。","image":""},{"id":262,"family":1,"name":"CupertinoSegmentedControl","nameCN":"iOS多栏切换","linkWidget":"33","lever":4,"info":"iOS风格的多按钮栏,表现和ToggleButtons类似,可指定内边距。","image":""},{"id":263,"family":2,"name":"FractionalTranslation","nameCN":"分度偏移","linkWidget":"","lever":3,"info":"通过offset属性将子组件进行偏移,偏移量为OffSet横纵*子组件大小。","image":""},{"id":264,"family":2,"name":"RepaintBoundary","nameCN":"重绘边界","linkWidget":"166","lever":5,"info":"为子组件创建一个单独的显示列表,提升性能。源码中在TextField、DrawerController、Scrollbar、Sliver等组件中均有应用","image":""},{"id":277,"family":2,"name":"ShaderMask","nameCN":"着色器遮罩","linkWidget":"88,38","lever":4,"info":"可容纳一个孩子,并通过着色器来对孩子进行着色,可指定混色模式。通常用于组件渐变色处理。","image":""},{"id":278,"family":2,"name":"BackdropFilter","nameCN":"背景滤镜","linkWidget":"88,97,67","lever":4,"info":"可容纳一个孩子,并将背景进行模糊滤镜。可以通过Stack将背景模糊实现组件的模糊效果。","image":""},{"id":279,"family":2,"name":"PhysicalShape","nameCN":"物理形状","linkWidget":"69","lever":4,"info":"可以让子组件按照路径进行剪裁,并且可以指定背景色、影深、阴影颜色、剪切行为。","image":""},{"id":285,"family":2,"name":"CustomSingleChildLayout","nameCN":"通用单子布局","linkWidget":"341","lever":3,"info":"可容纳一个子组件,并指定代理类对子组件进行排布。代理类可获取父容器区域和子组件的区域大小,及区域约束情况。","image":""},{"id":287,"family":2,"name":"LayoutBuilder","nameCN":"布局构造器","linkWidget":"","lever":4,"info":"可以检测到父容器的区域大小,并根据父容器的尺寸信息可以完成自定义布局。是一个非常实用的布局组件。","image":""},{"id":292,"family":2,"name":"IgnorePointer","nameCN":"忽视点击","linkWidget":"295,146,149,150","lever":4,"info":"容纳一个子组件,可以通过指定ignoring属性,来决定孩子是否忽略手势事件,其本身不接受事件。","image":""},{"id":293,"family":1,"name":"MouseRegion","nameCN":"鼠标区域","linkWidget":"","lever":3,"info":"用于鼠标事件监听的组件,通常用于桌面和Web平台,可监听鼠标的移入、移除、移动事件。","image":""},{"id":295,"family":2,"name":"AbsorbPointer","nameCN":"吸收点击","linkWidget":"146,149,150,292","lever":4,"info":"容纳一个子组件,可以通过指定ignoring属性,来决定孩子是否忽略手势事件,其本身接受事件。","image":""},{"id":297,"family":2,"name":"IntrinsicWidth","nameCN":"固有宽","linkWidget":"298","lever":4,"info":"根据子元素的固有宽度度调整其子元素大小的组件,可解决很多布局的疑难杂症,但相对昂贵。","image":""},{"id":298,"family":2,"name":"IntrinsicHeight","nameCN":"固有高","linkWidget":"297","lever":4,"info":"根据子元素的固有高度调整其子元素大小的组件,可解决很多布局的疑难杂症,但相对昂贵。","image":""},{"id":307,"family":4,"name":"SliverOverlapAbsorber","nameCN":"重叠吸收器","linkWidget":"251,308","lever":3,"info":"包裹另一个的sliver,并迫使其布局范围被视为重叠。需要和SliverOverlapInjector联用。","image":""},{"id":308,"family":4,"name":"SliverOverlapInjector","nameCN":"重叠注射器","linkWidget":"251,307","lever":3,"info":"一个sliver,需要和SliverOverlapAbsorber联用,处理视图重叠问题。","image":""},{"id":312,"family":6,"name":"PerformanceOverlay","nameCN":"性能浮层","linkWidget":"65","lever":2,"info":"可以非常方便地开启性能监测的两个柱图,方便查看刷新界面时帧率的变化情况。","image":""},{"id":313,"family":6,"name":"RawImage","nameCN":"原图片","linkWidget":"38","lever":2,"info":"是实现Image组件的核心组件,可以显示ui的Image,基本属性同Image,一般很少单独使用。","image":""},{"id":315,"family":5,"name":"LayoutId","nameCN":"布局Id","linkWidget":"341","lever":2,"info":"只能用于CustomMultiChildLayout组件中,为其子组件标识身份。","image":""},{"id":324,"family":5,"name":"DefaultTextStyle","nameCN":"默认字体样式","linkWidget":"2,114,124","lever":3,"info":"可容纳一个孩子,为后代的文字指定默认样式。常用于多个相同文字的样式统一,避免一一设置。","image":""},{"id":325,"family":5,"name":"IconTheme","nameCN":"图标样式","linkWidget":"6","lever":3,"info":"可容纳一个孩子,为后代的图标指定默认样式。常用于多个相同图标的样式统一,避免一一设置。","image":""},{"id":326,"family":5,"name":"ButtonTheme","nameCN":"按钮样式","linkWidget":"23,25,26,27","lever":3,"info":"主要用于为后代的Button类型组件统一设置默认属性,也可以通过该组件获取默认Button的属性。","image":""},{"id":327,"family":5,"name":"MaterialBannerTheme","nameCN":"横幅样式","linkWidget":"211","lever":2,"info":"主要用于为后代的MaterialBanner组件统一设置默认属性,也可以通过该组件获取默认MaterialBanner的属性。","image":""},{"id":328,"family":5,"name":"ChipTheme","nameCN":"小条样式","linkWidget":"11,153,12,13,14,15","lever":3,"info":"主要用于为后代的Chip类型组件统一设置默认属性,也可以通过该组件获取默认Chip的属性。","image":""},{"id":329,"family":5,"name":"DividerTheme","nameCN":"分割线样式","linkWidget":"34,35","lever":3,"info":"主要用于为后代的Divider类型组件统一设置默认属性,也可以通过该组件获取默认Divider的属性。","image":""},{"id":330,"family":5,"name":"PopupMenuTheme","nameCN":"弹出菜单样式","linkWidget":"56","lever":2,"info":"主要用于为后代的PopupMenuButton组件统一设置默认属性,也可以通过该组件获取默认PopupMenu的属性。","image":""},{"id":331,"family":5,"name":"SliderTheme","nameCN":"滑块样式","linkWidget":"42","lever":3,"info":"可容纳一个孩子,为后代的Slider指定默认样式。常用于Slider的样式统一,避免一一设置,也可以对Slider进行样式定制。","image":""},{"id":332,"family":5,"name":"ToggleButtonsTheme","nameCN":"滑块样式","linkWidget":"33","lever":2,"info":"主要用于为后代的ToggleButtons组件统一设置默认属性,也可以通过该组件获取默认ToggleButtons的属性。","image":""},{"id":333,"family":5,"name":"TooltipTheme","nameCN":"提示主题","linkWidget":"50","lever":2,"info":"主要用于为后代的Tooltip组件统一设置默认属性,也可以通过该组件获取默认TooltipTheme的属性。","image":""},{"id":334,"family":5,"name":"ListTileTheme","nameCN":"ListTile主题","linkWidget":"16","lever":2,"info":"主要用于为后代的ListTile组件统一设置默认属性,也可以通过该组件获取默认ListTile的属性。","image":""},{"id":338,"family":5,"name":"ButtonBarTheme","nameCN":"按钮条主题","linkWidget":"29","lever":2,"info":"主要用于为后代的ButtonBar组件统一设置默认属性,也可以通过该组件获取默认ButtonBarTheme的属性。","image":""},{"id":340,"family":3,"name":"Viewport","nameCN":"视口组件","linkWidget":"253,349","lever":1,"info":"通常用于为滑动视图提供视口,仅构建显示和预加载的部位。可指定预加载的长度、滑动轴向等。是ScrollView的核心实现组件之一,一般不直接使用。","image":""},{"id":341,"family":3,"name":"CustomMultiChildLayout","nameCN":"通用多子布局","linkWidget":"315,285","lever":4,"info":"使用一个代理类对子组件集进行布局控制,子组件必须使用LayoutId组件进行标识。","image":""},{"id":342,"family":3,"name":"ListBody","nameCN":"列表体","linkWidget":"162","lever":1,"info":"将若干子组件按照轴向进行排列,可设置的属性很少,一般很少使用,而选择使用ListView。","image":""},{"id":351,"family":1,"name":"InteractiveViewer","nameCN":"交互视图","linkWidget":"147,146,78","lever":4,"info":"主要对移动、缩放等手势交互进行封装,简化使用,可指定移动边界、缩放比例、手势监听等。","image":""},{"id":352,"family":0,"name":"CupertinoDialogAction","nameCN":"交互视图","linkWidget":"129","lever":1,"info":" 一个简单的按钮,通常用于CupertinoAlertDialog中,一般不单独使用。","image":""}]
\ No newline at end of file
diff --git a/assets/flutter.db b/assets/flutter.db
index b1545c3d..b09da0bc 100644
Binary files a/assets/flutter.db and b/assets/flutter.db differ
diff --git a/assets/fonts/BalooBhai2-Regular.ttf b/assets/fonts/BalooBhai2-Regular.ttf
index e69de29b..21a94309 100644
Binary files a/assets/fonts/BalooBhai2-Regular.ttf and b/assets/fonts/BalooBhai2-Regular.ttf differ
diff --git a/assets/fonts/CHOPS.ttf b/assets/fonts/CHOPS.ttf
new file mode 100644
index 00000000..137e1db1
Binary files /dev/null and b/assets/fonts/CHOPS.ttf differ
diff --git a/assets/fonts/ComicNeue-Regular.ttf b/assets/fonts/ComicNeue-Regular.ttf
index e69de29b..cbfed157 100644
Binary files a/assets/fonts/ComicNeue-Regular.ttf and b/assets/fonts/ComicNeue-Regular.ttf differ
diff --git a/assets/fonts/Inconsolata-Regular.ttf b/assets/fonts/Inconsolata-Regular.ttf
index e69de29b..18a07080 100644
Binary files a/assets/fonts/Inconsolata-Regular.ttf and b/assets/fonts/Inconsolata-Regular.ttf differ
diff --git a/assets/fonts/IndieFlower-Regular.ttf b/assets/fonts/IndieFlower-Regular.ttf
index e69de29b..1070aacd 100644
Binary files a/assets/fonts/IndieFlower-Regular.ttf and b/assets/fonts/IndieFlower-Regular.ttf differ
diff --git a/assets/fonts/Neucha-Regular.ttf b/assets/fonts/Neucha-Regular.ttf
index e69de29b..a9b91580 100644
Binary files a/assets/fonts/Neucha-Regular.ttf and b/assets/fonts/Neucha-Regular.ttf differ
diff --git a/assets/iconfont/iconfont.ttf b/assets/iconfont/iconfont.ttf
deleted file mode 100644
index 5860038f..00000000
Binary files a/assets/iconfont/iconfont.ttf and /dev/null differ
diff --git a/assets/iconfont/toly_icon.ttf b/assets/iconfont/toly_icon.ttf
new file mode 100644
index 00000000..f112440c
Binary files /dev/null and b/assets/iconfont/toly_icon.ttf differ
diff --git a/assets/images/caver.webp b/assets/images/caver.webp
index 426ab0cc..3d4102c0 100644
Binary files a/assets/images/caver.webp and b/assets/images/caver.webp differ
diff --git a/assets/images/coffee_wx.webp b/assets/images/coffee_wx.webp
new file mode 100644
index 00000000..34298068
Binary files /dev/null and b/assets/images/coffee_wx.webp differ
diff --git a/assets/images/coffee_wx_ac.webp b/assets/images/coffee_wx_ac.webp
new file mode 100644
index 00000000..1d21f46f
Binary files /dev/null and b/assets/images/coffee_wx_ac.webp differ
diff --git a/assets/images/coffee_zfb.webp b/assets/images/coffee_zfb.webp
new file mode 100644
index 00000000..79859859
Binary files /dev/null and b/assets/images/coffee_zfb.webp differ
diff --git a/assets/images/widgets/Autocomplete.svg b/assets/images/widgets/Autocomplete.svg
new file mode 100644
index 00000000..653b4f5a
--- /dev/null
+++ b/assets/images/widgets/Autocomplete.svg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/widgets/Banner.svg b/assets/images/widgets/Banner.svg
new file mode 100644
index 00000000..e4f8b66d
--- /dev/null
+++ b/assets/images/widgets/Banner.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Card.svg b/assets/images/widgets/Card.svg
new file mode 100644
index 00000000..b69099b8
--- /dev/null
+++ b/assets/images/widgets/Card.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Card.webp b/assets/images/widgets/Card.webp
deleted file mode 100644
index 9f8452a4..00000000
Binary files a/assets/images/widgets/Card.webp and /dev/null differ
diff --git a/assets/images/widgets/Chip.svg b/assets/images/widgets/Chip.svg
new file mode 100644
index 00000000..cea4cbee
--- /dev/null
+++ b/assets/images/widgets/Chip.svg
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Chip.webp b/assets/images/widgets/Chip.webp
deleted file mode 100644
index 1be3bfa8..00000000
Binary files a/assets/images/widgets/Chip.webp and /dev/null differ
diff --git a/assets/images/widgets/CircleAvatar.svg b/assets/images/widgets/CircleAvatar.svg
new file mode 100644
index 00000000..eafafcb4
--- /dev/null
+++ b/assets/images/widgets/CircleAvatar.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Container.svg b/assets/images/widgets/Container.svg
new file mode 100644
index 00000000..be18043d
--- /dev/null
+++ b/assets/images/widgets/Container.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Container.webp b/assets/images/widgets/Container.webp
deleted file mode 100644
index 0cc509a9..00000000
Binary files a/assets/images/widgets/Container.webp and /dev/null differ
diff --git a/assets/images/widgets/FilterChip.svg b/assets/images/widgets/FilterChip.svg
new file mode 100644
index 00000000..7a3f6fdd
--- /dev/null
+++ b/assets/images/widgets/FilterChip.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/FloatingActionButton.svg b/assets/images/widgets/FloatingActionButton.svg
new file mode 100644
index 00000000..dfe23295
--- /dev/null
+++ b/assets/images/widgets/FloatingActionButton.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/widgets/FlutterLogo.svg b/assets/images/widgets/FlutterLogo.svg
new file mode 100644
index 00000000..6a82787f
--- /dev/null
+++ b/assets/images/widgets/FlutterLogo.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/assets/images/widgets/GestureDetector.svg b/assets/images/widgets/GestureDetector.svg
new file mode 100644
index 00000000..8d3a0001
--- /dev/null
+++ b/assets/images/widgets/GestureDetector.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/assets/images/widgets/GridView.svg b/assets/images/widgets/GridView.svg
new file mode 100644
index 00000000..2d7f6874
--- /dev/null
+++ b/assets/images/widgets/GridView.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Icon.svg b/assets/images/widgets/Icon.svg
new file mode 100644
index 00000000..dd64950c
--- /dev/null
+++ b/assets/images/widgets/Icon.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/fonts/CHOPS.TTF b/assets/images/widgets/Image.svg
similarity index 100%
rename from assets/fonts/CHOPS.TTF
rename to assets/images/widgets/Image.svg
diff --git a/assets/images/widgets/InputChip.svg b/assets/images/widgets/InputChip.svg
new file mode 100644
index 00000000..b739a7ae
--- /dev/null
+++ b/assets/images/widgets/InputChip.svg
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/InputChip.webp b/assets/images/widgets/InputChip.webp
deleted file mode 100644
index c6bb7883..00000000
Binary files a/assets/images/widgets/InputChip.webp and /dev/null differ
diff --git a/assets/images/widgets/ListView.svg b/assets/images/widgets/ListView.svg
new file mode 100644
index 00000000..4e10e658
--- /dev/null
+++ b/assets/images/widgets/ListView.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/MaterialButton.svg b/assets/images/widgets/MaterialButton.svg
new file mode 100644
index 00000000..7ace688c
--- /dev/null
+++ b/assets/images/widgets/MaterialButton.svg
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/PageView.svg b/assets/images/widgets/PageView.svg
new file mode 100644
index 00000000..5dc3a701
--- /dev/null
+++ b/assets/images/widgets/PageView.svg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/widgets/RichText.svg b/assets/images/widgets/RichText.svg
new file mode 100644
index 00000000..0dd5f661
--- /dev/null
+++ b/assets/images/widgets/RichText.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/assets/images/widgets/SingleChildScrollView.svg b/assets/images/widgets/SingleChildScrollView.svg
new file mode 100644
index 00000000..baddde13
--- /dev/null
+++ b/assets/images/widgets/SingleChildScrollView.svg
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/widgets/Text.png b/assets/images/widgets/Text.png
new file mode 100644
index 00000000..5f690258
Binary files /dev/null and b/assets/images/widgets/Text.png differ
diff --git a/assets/images/widgets/Text.svg b/assets/images/widgets/Text.svg
new file mode 100644
index 00000000..2b327a5d
--- /dev/null
+++ b/assets/images/widgets/Text.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/assets/images/widgets/Widget.svg b/assets/images/widgets/Widget.svg
new file mode 100644
index 00000000..f9299096
--- /dev/null
+++ b/assets/images/widgets/Widget.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/assets/images/wxgzh.webp b/assets/images/wxgzh.webp
new file mode 100644
index 00000000..0a44c72c
Binary files /dev/null and b/assets/images/wxgzh.webp differ
diff --git a/assets/version.json b/assets/version.json
index 79dcc07a..231c882a 100644
--- a/assets/version.json
+++ b/assets/version.json
@@ -1,3 +1,3 @@
{
- "dbVersion": 2
+ "dbVersion": 4
}
\ No newline at end of file
diff --git a/desiredFileName.txt b/desiredFileName.txt
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/desiredFileName.txt
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/devtools_options.yaml b/devtools_options.yaml
new file mode 100644
index 00000000..fa0b357c
--- /dev/null
+++ b/devtools_options.yaml
@@ -0,0 +1,3 @@
+description: This file stores settings for Dart & Flutter DevTools.
+documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
+extensions:
diff --git a/doc/ewm/coffee1.png b/doc/ewm/coffee1.png
new file mode 100644
index 00000000..dbbf38bc
Binary files /dev/null and b/doc/ewm/coffee1.png differ
diff --git a/doc/screens/preview.webp b/doc/screens/preview.webp
new file mode 100644
index 00000000..79cf8b00
Binary files /dev/null and b/doc/screens/preview.webp differ
diff --git a/doc/version/3.1.0.md b/doc/version/3.1.0.md
new file mode 100644
index 00000000..d551bad2
--- /dev/null
+++ b/doc/version/3.1.0.md
@@ -0,0 +1,10 @@
+桌面版:
+windows/macos 支持应用内更新,优化更新过程交互
+增加: 知识集锦/布局宝库
+增加 Ctrl+F 全局搜索功能
+
+全端:
+增加收录组件,目前共 354 个
+支持寻路算法演绎
+优化组件详情展示
+支持复制局部代码
diff --git a/doc/version/3.2.0.md b/doc/version/3.2.0.md
new file mode 100644
index 00000000..9afbc216
--- /dev/null
+++ b/doc/version/3.2.0.md
@@ -0,0 +1,9 @@
+全端:
+增加最新咨询功能
+优化组件列表展示,增加logo设计图
+增加世界留言板
+优化项目结构
+组件数据支持 10 国语言国际化
+
+下载失败,可到下面网站下载最新版
+https://gitee.com/toly1994328/FlutterUnit/releases
\ No newline at end of file
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f9..9625e105 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 11.0
diff --git a/ios/Podfile b/ios/Podfile
index 1e8c3c90..88359b22 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index d163a216..42719a09 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,4 +1,41 @@
PODS:
+ - connectivity_plus (0.0.1):
+ - Flutter
+ - ReachabilitySwift
+ - DKImagePickerController/Core (4.3.4):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.4)
+ - DKImagePickerController/PhotoGallery (4.3.4):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.4)
+ - DKPhotoGallery (0.0.17):
+ - DKPhotoGallery/Core (= 0.0.17)
+ - DKPhotoGallery/Model (= 0.0.17)
+ - DKPhotoGallery/Preview (= 0.0.17)
+ - DKPhotoGallery/Resource (= 0.0.17)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
- Flutter (1.0.0)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
@@ -9,6 +46,10 @@ PODS:
- Flutter
- r_upgrade (0.0.1):
- Flutter
+ - ReachabilitySwift (5.0.0)
+ - SDWebImage (5.15.4):
+ - SDWebImage/Core (= 5.15.4)
+ - SDWebImage/Core (5.15.4)
- share_plus (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
@@ -16,10 +57,15 @@ PODS:
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
+ - SwiftyGif (5.4.4)
- url_launcher_ios (0.0.1):
- Flutter
+ - webview_flutter_wkwebview (0.0.1):
+ - Flutter
DEPENDENCIES:
+ - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
@@ -28,12 +74,22 @@ DEPENDENCIES:
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS:
trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
- FMDB
+ - ReachabilitySwift
+ - SDWebImage
+ - SwiftyGif
EXTERNAL SOURCES:
+ connectivity_plus:
+ :path: ".symlinks/plugins/connectivity_plus/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
package_info_plus:
@@ -50,18 +106,28 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
+ webview_flutter_wkwebview:
+ :path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
- Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
+ connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
+ DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
+ DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
+ file_picker: ce3938a0df3cc1ef404671531facef740d03f920
+ Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
- package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
- path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5
+ package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
+ path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114
- share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
+ ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
+ SDWebImage: 1c39de67663e5eebb2f41324d5d580eeea12dd4c
+ share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
+ SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
+ webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
-COCOAPODS: 1.10.1
+COCOAPODS: 1.12.0
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 6b87be1b..4d990781 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 50;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -76,7 +76,6 @@
8124494143C478106CBB5535 /* Pods-Runner.release.xcconfig */,
64130BD95C8A67B133F535A6 /* Pods-Runner.profile.xcconfig */,
);
- name = Pods;
path = Pods;
sourceTree = "";
};
@@ -200,10 +199,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -231,6 +232,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -340,7 +342,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -355,15 +357,25 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = XQPP7CHG9D;
+ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = XQPP7CHG9D;
ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DISABLE_PUSH_NOTIFICATIONS=1",
+ );
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = FlutterUnit;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.toly1994.flutterUnit;
+ MARKETING_VERSION = 2.9.2;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.toly1994.flutter-unit";
PRODUCT_NAME = "$(TARGET_NAME)";
+ "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = flutter_unit_profile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@@ -417,7 +429,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -466,7 +478,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -483,15 +495,29 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = XQPP7CHG9D;
ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DISABLE_PUSH_NOTIFICATIONS=1",
+ );
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = FlutterUnit;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.toly1994.flutterUnit;
+ MARKETING_VERSION = 2.9.2;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.toly1994.flutter-unit";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = flutter_unit_profile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -505,15 +531,29 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = "";
+ "DEVELOPMENT_TEAM[sdk=iphoneos*]" = XQPP7CHG9D;
ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "DISABLE_PUSH_NOTIFICATIONS=1",
+ );
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = FlutterUnit;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.toly1994.flutterUnit;
+ MARKETING_VERSION = 2.9.2;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.toly1994.flutter-unit";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = flutter_unit_profile;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
index dc9ada47..eba2268a 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
index 28c6bf03..5768d4c4 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
index 2ccbfd96..a1610c71 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
index f091b6b0..157d749a 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
index 4cde1211..62e62180 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
index d0ef06e7..adab1c1e 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
index dcdc2306..5e5dba9f 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
index 2ccbfd96..a1610c71 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
index c8f9ed8f..0e166cfa 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
index a6d6b860..9394bba7 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png
new file mode 100644
index 00000000..157d749a
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
index a6d6b860..9394bba7 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
index 75b2d164..09b0e89e 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
index c4df70d3..f4f8b8c4 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
index 6a84f41e..91e929a3 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
index d0e1f585..95decc3b 100644
Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 58fd58cf..cf0fae5e 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,6 +2,8 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -24,6 +26,8 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ UIApplicationSupportsIndirectInputEvents
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -43,5 +47,9 @@
UIViewControllerBasedStatusBarAppearance
+ NSPhotoLibraryUsageDescription
+ FlutterUnit 申请访问相册,以提升您的图片选择功能的体验
+ NSPhotoLibraryAddUsageDescription
+ FlutterUnit 申请访问相册,以支持您保存图片到相册
diff --git a/l10n.yaml b/l10n.yaml
new file mode 100644
index 00000000..7312142f
--- /dev/null
+++ b/l10n.yaml
@@ -0,0 +1,10 @@
+arb-dir: lib/src/l10n/arb
+template-arb-file: app_zh.arb
+output-localization-file: app_l10n.dart
+
+
+synthetic-package: false
+output-dir: lib/src/l10n/gen
+output-class: AppL10n
+nullable-getter: false
+untranslated-messages-file: desiredFileName.txt
\ No newline at end of file
diff --git a/lib/.gitignore b/lib/.gitignore
deleted file mode 100644
index a47f7e00..00000000
--- a/lib/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/temp/
\ No newline at end of file
diff --git a/lib/app/bloc_wrapper.dart b/lib/app/bloc_wrapper.dart
deleted file mode 100644
index 90319835..00000000
--- a/lib/app/bloc_wrapper.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:app_update/app_update.dart';
-import 'package:authentication/authentication.dart';
-import 'package:db_storage/db_storage.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/painter_system/bloc/gallery_unit/bloc.dart';
-import 'package:widget_module/blocs/blocs.dart';
-import 'package:widget_repository/widget_repository.dart';
-
-
-
-/// create by 张风捷特烈 on 2020/4/28
-/// contact me by email 1981462002@qq.com
-/// 说明: Bloc提供器包裹层
-
-// final AppStart storage = AppStart();
-
-class BlocWrapper extends StatefulWidget {
- final Widget child;
-
- const BlocWrapper({Key? key, required this.child}) : super(key: key);
-
- @override
- _BlocWrapperState createState() => _BlocWrapperState();
-}
-
-class _BlocWrapperState extends State {
- final WidgetRepository repository = const WidgetDbRepository();
-
- final CategoryBloc categoryBloc= CategoryBloc(repository: CategoryDbRepository());
- final AuthRepository authRepository = HttpAuthRepository();
-
- @override
- Widget build(BuildContext context) {
- return MultiBlocProvider(
- providers: [
- // 全局 bloc : 维护应用存储状态、更新、认证
- BlocProvider(create: (_) => AppBloc(AppStateRepository())..initApp()),
- BlocProvider(create: (_) => UpdateBloc()),
- BlocProvider(create: (_) => AuthBloc(repository: authRepository)..add(const AppStarted())),
-
- BlocProvider(create: (_) => WidgetsBloc(repository: repository)),
- BlocProvider(create: (_) => categoryBloc),
- BlocProvider(create: (_) => LikeWidgetBloc(repository: repository)),
- BlocProvider(create: (_) => CategoryWidgetBloc(categoryBloc: categoryBloc)),
- BlocProvider(create: (_) => GalleryUnitBloc()..loadGalleryInfo()),
- ], child: widget.child);
- }
-
- @override
- void dispose() {
- categoryBloc.close();
- LocalDb.instance.closeDb();
- super.dispose();
- }
-}
diff --git a/lib/app/flutter_unit.dart b/lib/app/flutter_unit.dart
deleted file mode 100644
index 9b03759c..00000000
--- a/lib/app/flutter_unit.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_localizations/flutter_localizations.dart';
-
-import 'package:flutter_unit/app/router/unit_router.dart';
-import 'package:flutter_unit/app/views/splash/standard_unit_splash.dart';
-import 'package:old_fancy_mobile_ui/bloc/color_change_bloc.dart';
-
-
-/// create by 张风捷特烈 on 2020/4/28
-/// contact me by email 1981462002@qq.com
-/// 说明: 主程序
-
-class FlutterUnit extends StatelessWidget {
- const FlutterUnit({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder(builder: (_, state) {
- return BlocProvider(
- create: (_) => ColorChangeCubit(Cons.tabColors[0]),
- child: DefaultTextStyle(
- style: TextStyle(fontFamily: state.fontFamily),
- child: MaterialApp(
- showPerformanceOverlay: state.showPerformanceOverlay,
- title: StrUnit.appName,
- debugShowCheckedModeBanner: false,
- onGenerateRoute: UnitRouters.generateRoute,
- localizationsDelegates: GlobalMaterialLocalizations.delegates,
- supportedLocales: const [
- Locale('zh', 'CN'),
- ],
- themeMode: ThemeMode.light,
- // themeMode: ThemeMode.dark,
- darkTheme: AppTheme.darkTheme(state),
- theme: AppTheme.lightTheme(state),
- // theme: ThemeData(
- // primarySwatch: state.themeColor,
- // fontFamily: state.fontFamily,
- // ),
- home: const StandardUnitSplash(),
- ),
- ),
- );
- });
- }
-}
diff --git a/lib/app/navigation/desk_ui/unit_desk_navigation.dart b/lib/app/navigation/desk_ui/unit_desk_navigation.dart
deleted file mode 100644
index 0b9b82c3..00000000
--- a/lib/app/navigation/desk_ui/unit_desk_navigation.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/app/plateform_adapter/window/windows_adapter.dart';
-import 'package:flutter_unit/app/views/unit_todo/layout_unit_page.dart';
-import 'package:flutter_unit/app/views/unit_todo/point_unit_page.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter_unit/code_gen/code_gen_page.dart';
-
-import 'package:flutter_unit/painter_system/gallery_unit.dart';
-import 'package:flutter_unit/widget_ui/desk_ui/widget_panel/widget_panel.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/collect_page.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/home_right_drawer.dart';
-import 'package:old_fancy_mobile_ui/bloc/color_change_bloc.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-import '../../../point_system/views/desk_ui/desk_point_page.dart';
-import '../home_drawer.dart';
-import 'unit_rail_navigation.dart';
-
-class UnitDeskNavigation extends StatefulWidget {
-
- const UnitDeskNavigation();
-
- @override
- _UnitDeskNavigationState createState() => _UnitDeskNavigationState();
-
-}
-
-class _UnitDeskNavigationState extends State {
- late PageController _controller; //页面控制器,初始0
- int _currentIndex = 0;
-
- @override
- void initState() {
- super.initState();
- _controller = PageController();
-
- // ActionUnit.searchAction.onSearch = () {
- // Navigator.of(context).pushNamed(UnitRouter.search);
- // };
- }
-
- @override
- void dispose() {
- _controller.dispose(); //释放控制器
- super.dispose();
- }
-
- // 构建悬浮按钮工具
- // Widget wrapOverlayTool({required Widget child}) => Builder(
- // builder: (ctx) => OverlayToolWrapper(
- // child: child,
- // ));
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- drawer: const HomeDrawer(),
- endDrawer: const HomeRightDrawer(),
- body: Row(
- children: [
- UnitRailNavigation(
- selectedIndex: _currentIndex,
- onItemClick: _onItemClick, itemData: {
- //底栏图标
- "组件集录": TolyIcon.icon_layout, "收藏集录": TolyIcon.icon_star,
- "绘制集录": Icons.palette, "代码生成": TolyIcon.icon_fast,
- "要点集录": TolyIcon.icon_bug,
- },
- ),
- // _buildLeftNav(),
- Expanded(
- child: PageView(
- physics: const NeverScrollableScrollPhysics(),
- //使用PageView实现页面的切换
- controller: _controller,
- children: const [
- DeskWidgetPanel(),
- CollectPageAdapter(),
- GalleryUnit(),
- CodeGenPage(),
- DeskPointPage(),
- ],
- ),
- ),
- ],
- ),
- );
- }
-
- void _onItemClick(int value) {
- _currentIndex = value;
- _controller.jumpToPage(_currentIndex);
- setState(() {
-
- });
- }
-}
-
-
diff --git a/lib/app/navigation/desk_ui/unit_rail_navigation.dart b/lib/app/navigation/desk_ui/unit_rail_navigation.dart
deleted file mode 100644
index ca4dc363..00000000
--- a/lib/app/navigation/desk_ui/unit_rail_navigation.dart
+++ /dev/null
@@ -1,302 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_unit/app/plateform_adapter/window/windows_adapter.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-class UnitRailNavigation extends StatelessWidget {
- final ValueChanged onItemClick;
- final int selectedIndex;
- final Map itemData;
-
- const UnitRailNavigation(
- {Key? key,
- required this.onItemClick,
- required this.selectedIndex,
- required this.itemData})
- : super(key: key);
-
- List get info => itemData.keys.toList();
- List get icons => itemData.values.toList();
-
- @override
- Widget build(BuildContext context) {
- // NavigationRail
- return DragToMoveAreaNoDouble(
- child: Container(
- padding: const EdgeInsets.only(top: 20),
- alignment: Alignment.topCenter,
- margin: const EdgeInsets.only(right: 1),
- width: 120,
- decoration: const BoxDecoration(color: Color(0xff2C3036), boxShadow: [
- BoxShadow(color: Colors.grey, offset: Offset(1, 0), blurRadius: 2)
- ]),
- child: Column(
- children: [
- Wrap(
- direction: Axis.vertical,
- spacing: 10,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: const [
- CircleImage(
- image: AssetImage('assets/images/icon_head.webp'),
- size: 60,
- ),
- Text(
- '张风捷特烈',
- style: TextStyle(color: Colors.white70),
- )
- ],
- ),
- buildIcons(),
- const Divider(
- color: Colors.white,
- height: 1,
- endIndent: 20,
- ),
-// SizedBox(height: 60,),
- Expanded(
- flex: 5,
- child: Center(
- //const Size(120, 35)
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: info
- .asMap()
- .keys
- .map((int index) => _UnitRailMenu(
- onTap: () {onItemClick.call(index);},
- selected: selectedIndex == index,
- width: 120,
- height: 35, activeColor: Theme.of(context).primaryColor, inactiveColor:
- Colors.white.withAlpha(33), icon: icons[index],label: info[index],
- ))
- .toList(),
- )
-
- // RightNavBar(
- // itemData: Cons.iconMap,
- // onItemClick: onItemClick,
- // color: Theme.of(context).primaryColor,
- // ),
- ),
- ),
- Expanded(
- child: Container(),
- flex: 1,
- ),
- const Divider(
- indent: 20,
- color: Colors.white,
- height: 1,
- ),
- Builder(
- builder: (ctx) => FeedbackWidget(
- onPressed: () => Scaffold.of(ctx).openDrawer(),
- child: const Padding(
- padding: EdgeInsets.only(bottom: 20, top: 20),
- child: Icon(
- Icons.settings,
- color: Colors.white,
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- );
- ;
- }
-
- Widget buildIcons() {
- return Padding(
- padding: const EdgeInsets.only(bottom: 20, top: 20),
- child: Wrap(
- spacing: 5,
- children: [
- FeedbackWidget(
- onPressed: () => _launchURL("http://blog.toly1994.com/"),
- child: const Icon(
- TolyIcon.icon_item,
- color: Colors.white,
- ),
- ),
- FeedbackWidget(
- onPressed: () =>
- _launchURL("https://github.com/toly1994328/FlutterUnit"),
- child: const Icon(
- TolyIcon.icon_github,
- color: Colors.white,
- ),
- ),
- FeedbackWidget(
- onPressed: () =>
- _launchURL("https://juejin.im/user/5b42c0656fb9a04fe727eb37"),
- child: const Icon(
- TolyIcon.icon_juejin,
- color: Colors.white,
- ),
- ),
- ],
- ),
- );
- }
-
- _launchURL(String url) async {
- if (await canLaunch(url)) {
- await launch(url);
- } else {
- debugPrint('Could not launch $url');
- }
- }
-}
-
-class RightNavBar extends StatefulWidget {
- final Color color;
- final Map itemData;
- final ValueChanged onItemClick;
- final Size itemSize;
-
- RightNavBar({
- this.color = Colors.blue,
- required this.itemData,
- required this.onItemClick,
- this.itemSize = const Size(120, 35),
- });
-
- @override
- _RightNavBarState createState() => _RightNavBarState();
-}
-
-class _RightNavBarState extends State {
- int _position = 0;
-
- List get info => widget.itemData.keys.toList();
-
- @override
- Widget build(BuildContext context) {
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: info
- .map((e) => _buildChild(context, info.indexOf(e), widget.color))
- .toList(),
- );
- }
-
- Widget _buildChild(BuildContext context, int i, Color color) {
- var active = i == _position;
-
- return GestureDetector(
- onTap: () => _tapTab(i),
- child: Container(
- alignment: Alignment.topLeft,
- margin: const EdgeInsets.only(top: 10),
- width: widget.itemSize.width,
- child: UnconstrainedBox(
- child: Container(
- alignment: Alignment.center,
- decoration: BoxDecoration(
- color: active ? widget.color : Colors.white.withAlpha(33),
- borderRadius: const BorderRadius.only(
- topRight: Radius.circular(20),
- bottomRight: Radius.circular(20))),
- width: active
- ? widget.itemSize.width * 0.95
- : widget.itemSize.width * 0.85,
- height: widget.itemSize.height,
- child: Wrap(
- spacing: 10,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: [
- Icon(
- widget.itemData[info[i]],
- size: active ? 24 : 20,
- color: active ? Colors.white : Colors.white70,
- ),
- Text(
- info[i],
- style: TextStyle(
- color: active ? Colors.white : Colors.white70,
- ),
- ),
- ],
- ),
- ),
- ),
- ));
- }
-
- _tapTab(int i) {
- setState(() {
- _position = i;
- if (widget.onItemClick != null) {
- widget.onItemClick(_position);
- }
- });
- }
-}
-
-class _UnitRailMenu extends StatelessWidget {
- final VoidCallback onTap;
- final bool selected;
- final Color activeColor;
- final Color inactiveColor;
- final double width;
- final double height;
- final IconData icon;
- final String label;
-
- const _UnitRailMenu({
- Key? key,
- required this.onTap,
- required this.selected,
- required this.width,
- required this.activeColor,
- required this.inactiveColor,
- required this.height,
- required this.icon,
- required this.label,
- }) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- onTap: onTap,
- child: Container(
- alignment: Alignment.topLeft,
- margin: const EdgeInsets.only(top: 10),
- width: width,
- child: UnconstrainedBox(
- child: Container(
- alignment: Alignment.center,
- decoration: BoxDecoration(
- color: selected ? activeColor : inactiveColor,
- borderRadius: const BorderRadius.only(
- topRight: Radius.circular(20),
- bottomRight: Radius.circular(20))),
- width: selected ? width * 0.95 : width * 0.85,
- height: height,
- child: Wrap(
- spacing: 10,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: [
- Icon(
- icon,
- size: selected ? 24 : 20,
- color: selected ? Colors.white : Colors.white70,
- ),
- Text(
- label,
- style: TextStyle(
- fontSize: 12,
- color: selected ? Colors.white : Colors.white70,
- ),
- ),
- ],
- ),
- ),
- ),
- ));
- }
-}
diff --git a/lib/app/navigation/pure_bottom_bar.dart b/lib/app/navigation/pure_bottom_bar.dart
deleted file mode 100644
index b799b3e0..00000000
--- a/lib/app/navigation/pure_bottom_bar.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-import 'package:old_fancy_mobile_ui/old_fancy_mobile_ui.dart';
-
-
-
-class PureBottomBar extends StatefulWidget {
- final int initPosition;
-
- // item 点击事件
- final IndexTapCallback? onItemTap;
-
- // item 长按事件
- final IndexLongTapCallback? onItemLongTap;
- const PureBottomBar({Key? key, this.onItemTap,this.onItemLongTap,this.initPosition=0}) : super(key: key);
-
- @override
- State createState() => _PureBottomBarState();
-}
-
-class _PureBottomBarState extends State {
- List get bottomBar => const['组件','绘制', '收藏','我的'];
-
- List get bottomBarIcon => const[
- TolyIcon.icon_layout,
- TolyIcon.dingzhi1,
- TolyIcon.icon_collect,
- TolyIcon.yonghu,
- ];
- int _position = 0;
-
- @override
- void initState() {
- super.initState();
- _position = widget.initPosition;
-
- }
-
- @override
- Widget build(BuildContext context) {
-
- return Wrap(
- children: [
- // Divider(height: 1,),
- BottomNavigationBar(
- backgroundColor: Colors.white,
- onTap: (position) {
- // checkTokenExpires();
- _position = position;
-
- widget.onItemTap?.call(_position);
- setState(() {
-
- // _controller.jumpToPage(_position);
- });
- },
- currentIndex: _position,
-
- elevation: 3,
- // fixedColor: themeColor.activeColor,
- type: BottomNavigationBarType.fixed,
- iconSize: 22,
- selectedItemColor: Theme.of(context).primaryColor,
- selectedLabelStyle: const TextStyle(fontWeight: FontWeight.bold),
- showUnselectedLabels: true,
- showSelectedLabels: true,
- // backgroundColor: themeColor.itemColor,
- items: bottomBar.asMap().keys.map((index) => BottomNavigationBarItem(label: bottomBar[index], icon: Icon(bottomBarIcon[index]))).toList(),
- ),
- ],
- );
- }
-}
diff --git a/lib/app/navigation/unit_drawer_header.dart b/lib/app/navigation/unit_drawer_header.dart
deleted file mode 100644
index 0d557292..00000000
--- a/lib/app/navigation/unit_drawer_header.dart
+++ /dev/null
@@ -1,87 +0,0 @@
-import 'package:flutter/material.dart';
-
-/// create by 张风捷特烈 on 2020-04-22
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class UnitDrawerHeader extends StatelessWidget {
- final Color color;
-
-
- const UnitDrawerHeader({Key? key, required this.color}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return DrawerHeader(
- padding: const EdgeInsets.only(top: 10, left: 15),
- decoration: const BoxDecoration(
- image: DecorationImage(
- image: AssetImage('assets/images/wy_300x200_filter.webp'),
- fit: BoxFit.cover),
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Wrap(
- spacing: 10,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: const [
- FlutterLogo(
- size: 35,
- ),
- Text(
- 'Flutter Unit',
- style: TextStyle(fontSize: 24, color: Colors.white, shadows: [
- Shadow(
- color: Colors.black,
- offset: Offset(1, 1),
- blurRadius: 3)
- ]),
- ),
- ],
- ),
- const SizedBox(
- height: 15,
- ),
- Text(
- 'The Unity Of Flutter, The Unity Of Coder.',
- style: TextStyle(fontSize: 15, color: Colors.white, shadows: [
- Shadow(color: color, offset: const Offset(.5, .5), blurRadius: 1)
- ]),
- ),
- const SizedBox(
- height: 5,
- ),
- Text(
- 'Flutter的联合,编程者的联合。',
- style: TextStyle(fontSize: 15, color: Colors.white, shadows: [
- Shadow(color: color, offset: const Offset(.5, .5), blurRadius: 1)
- ]),
- ),
- const SizedBox(
- height: 10,
- ),
- Row(
- children: const [
- Spacer(
- flex: 5,
- ),
- Text(
- '—— 张风捷特烈',
- style: TextStyle(fontSize: 15, color: Colors.white, shadows: [
- Shadow(
- color: Colors.orangeAccent,
- offset: Offset(.5, .5),
- blurRadius: 1)
- ]),
- ),
- Spacer(
- flex: 1,
- ),
- ],
- ),
- ],
- ),
- );
- }
-}
diff --git a/lib/app/navigation/unit_navigation.dart b/lib/app/navigation/unit_navigation.dart
deleted file mode 100644
index c10be2ca..00000000
--- a/lib/app/navigation/unit_navigation.dart
+++ /dev/null
@@ -1,172 +0,0 @@
-import 'dart:io';
-
-import 'package:app_config/app_config.dart';
-import 'package:app_update/app_update.dart';
-import 'package:authentication/authentication.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/painter_system/gallery_unit.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/collect_page.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/home_right_drawer.dart';
-import 'package:old_fancy_mobile_ui/bloc/color_change_bloc.dart';
-
-import 'package:old_fancy_mobile_ui/home_page/fancy_home_page.dart';
-import 'package:old_fancy_mobile_ui/old_fancy_mobile_ui.dart';
-import 'package:widget_module/blocs/blocs.dart';
-import 'package:flutter_unit/widget_ui/mobile/widget_panel/standard_home_page.dart';
-
-import 'pure_bottom_bar.dart';
-import 'desk_ui/unit_desk_navigation.dart';
-
-/// create by 张风捷特烈 on 2020-04-11
-/// contact me by email 1981462002@qq.com
-/// 说明: 主题结构 左右滑页 + 底部导航栏
-
-class UnitNavigation extends StatelessWidget {
- const UnitNavigation({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder(
- builder: (_, state) => LayoutBuilder(builder: (_, c) {
- if (c.maxWidth > 500) {
- return UnitDeskNavigation();
- }
- return UnitPhoneNavigation();
- }),
- );
- }
-}
-
-class UnitPhoneNavigation extends StatefulWidget {
- const UnitPhoneNavigation({Key? key}) : super(key: key);
-
- @override
- _UnitPhoneNavigationState createState() => _UnitPhoneNavigationState();
-}
-
-class _UnitPhoneNavigationState extends State {
- //页面控制器,初始 0
- final PageController _controller = PageController();
- int position = 0;
-
- // 禁止 PageView 滑动
- final ScrollPhysics _neverScroll = const NeverScrollableScrollPhysics();
-
- @override
- void initState() {
- super.initState();
- if (Platform.isAndroid) {
- BlocProvider.of(context)
- .add(const CheckUpdate(appName: 'FlutterUnit'));
- }
- }
-
- @override
- void dispose() {
- _controller.dispose(); //释放控制器
- super.dispose();
- }
-
- /// extendBody = true 凹嵌透明,需要处理底部 边距
- @override
- Widget build(BuildContext context) {
- AppStyle style = context.read().state.appStyle;
- bool isStandard = style == AppStyle.standard;
- return Scaffold(
- extendBody: true,
- endDrawer: const HomeRightDrawer(),
- floatingActionButtonLocation:
- isStandard ? null : FloatingActionButtonLocation.centerDocked,
- floatingActionButton: isStandard ? null : _buildSearchButton(context),
- body: PageView(
- physics: _neverScroll,
- controller: _controller,
- children: [
- if (style == AppStyle.fancy) const FancyHomePage(),
- if (style == AppStyle.standard) const StandardHomePage(),
- GalleryUnit(),
- CollectPageAdapter(),
- UserPage(),
- ],
- ),
- bottomNavigationBar: _buildBottomNav(context, style),
- );
- }
-
- bool get isDark => Theme.of(context).brightness == Brightness.dark;
-
- // 主页搜索按钮
- // 由于 按钮 颜色需要随 点击头部栏 状态而改变,
- // 使用 BlocBuilder 构建
- Widget _buildSearchButton(BuildContext context) {
- return BlocBuilder(builder: (_, state) {
- return FloatingActionButton(
- shape: const StadiumBorder(),
- elevation: 2,
- backgroundColor: isDark ? state.color : state.color,
- child: const Icon(Icons.search),
- onPressed: () => Navigator.of(context).pushNamed(UnitRouter.search),
- );
- });
- }
-
- // 由于 bottomNavigationBar 颜色需要随 点击头部栏 状态而改变,
- // 使用 BlocBuilder 构建
- Widget _buildBottomNav(BuildContext context, AppStyle style) {
- switch (style) {
- case AppStyle.standard:
- return Stack(
- children: [
- PureBottomBar(
- initPosition: position,
- onItemTap: _onTapBottomNav,
- onItemLongTap: _onItemLongTap,
- ),
- const Positioned(right: 26, top: 8, child: UpdateRedPoint())
- ],
- );
- case AppStyle.fancy:
- return BlocBuilder(
- builder: (context, state) {
- return UnitBottomBar(
- initPosition: position,
- color: state.color,
- onItemTap: _onTapBottomNav,
- onItemLongTap: _onItemLongTap,
- );
- },
- );
- }
- }
-
- // 点击底部按钮事件,切换页面
- void _onTapBottomNav(int index) {
- _controller.jumpToPage(index);
- position = index;
- if (!isDark) {
- late Color color;
- if (index != 0) {
- color = Theme.of(context).primaryColor;
- } else {
- color =
- Cons.tabColors[context.read().state.family.index];
- }
- context.read().change(color);
- }
-
- if (index == 2) {
- BlocProvider.of(context).add(const EventLoadLikeData());
- }
- }
-
- // 两侧
- void _onItemLongTap(BuildContext context, int index) {
- if (index == 0) {
- Scaffold.of(context).openDrawer();
- }
- if (index == 3) {
- Scaffold.of(context).openEndDrawer();
- }
- }
-}
diff --git a/lib/app/plateform_adapter/window/windows_adapter.dart b/lib/app/plateform_adapter/window/windows_adapter.dart
deleted file mode 100644
index 59e8a27e..00000000
--- a/lib/app/plateform_adapter/window/windows_adapter.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-import 'dart:io';
-
-import 'package:flutter/material.dart';
-import 'package:window_manager/window_manager.dart';
-
-class WindowsAdapter {
-
- static Future setSize() async {
- if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) {
- //仅对桌面端进行尺寸设置
- await windowManager.ensureInitialized();
- WindowOptions windowOptions = const WindowOptions(
- size: Size(900,600),
- minimumSize: Size(900,600),
- center: true,
- backgroundColor: Colors.transparent,
- skipTaskbar: false,
- titleBarStyle: TitleBarStyle.hidden,
- );
- windowManager.waitUntilReadyToShow(windowOptions, () async {
- await windowManager.setTitleBarStyle(TitleBarStyle.hidden,windowButtonVisibility: false);
- await windowManager.show();
- await windowManager.focus();
- });
- }
- }
-
-}
-
-
-class DragToMoveAreaNoDouble extends StatelessWidget {
- final Widget child;
-
- const DragToMoveAreaNoDouble({
- Key? key,
- required this.child,
- }) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- behavior: HitTestBehavior.translucent,
- onPanStart: (details) {
- windowManager.startDragging();
- },
- child: child,
- );
- }
-}
\ No newline at end of file
diff --git a/lib/app/router/unit_router.dart b/lib/app/router/unit_router.dart
deleted file mode 100644
index 4d3f505a..00000000
--- a/lib/app/router/unit_router.dart
+++ /dev/null
@@ -1,144 +0,0 @@
-// ignore_for_file: constant_identifier_names
-
-import 'dart:io';
-
-import 'package:app_config/app_config.dart';
-import 'package:authentication/authentication.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_unit/app/navigation/unit_navigation.dart';
-import 'package:flutter_unit/app/views/about/about_app_page.dart';
-import 'package:flutter_unit/app/views/about/about_me_page.dart';
-import 'package:flutter_unit/app/views/about/version_info.dart';
-import 'package:flutter_unit/app/views/data_manage/data_manage_page.dart';
-import 'package:flutter_unit/app/views/setting/code_style_setting.dart';
-import 'package:flutter_unit/app/views/setting/font_setting.dart';
-import 'package:flutter_unit/app/views/setting/item_style_setting.dart';
-import 'package:flutter_unit/app/views/setting/setting_page.dart';
-import 'package:flutter_unit/app/views/setting/theme_color_setting.dart';
-import 'package:flutter_unit/app/views/unit_todo/attr_unit_page.dart';
-import 'package:flutter_unit/app/views/unit_todo/layout_unit_page.dart';
-import 'package:flutter_unit/app/views/unit_todo/point_unit_page.dart';
-import 'package:flutter_unit/point_system/views/issues_point/issues_detail.dart';
-import 'package:flutter_unit/point_system/views/issues_point/issues_point_page.dart';
-import 'package:flutter_unit/widget_ui/desk_ui/widget_detail/widget_detail_page.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/category_detail.dart';
-import 'package:flutter_unit/widget_ui/mobile/category_page/collect_page.dart';
-import 'package:flutter_unit/widget_ui/mobile/search_page/search_page.dart';
-import 'package:flutter_unit/widget_ui/mobile/widget_detail/widget_detail_page.dart';
-import 'package:widget_repository/widget_repository.dart';
-
-
-class UnitRouters {
- static const String widget_detail = '/widget_detail';
-
- static const String detail = 'detail';
- static const String search = 'search_bloc';
-
-
- static const String collect = 'CollectPage';
- static const String point = 'IssuesPointPage';
- static const String point_detail = 'IssuesDetailPage';
-
- static const String setting = 'SettingPage';
- static const String font_setting = 'FountSettingPage';
- static const String theme_color_setting = 'ThemeColorSettingPage';
- static const String code_style_setting = 'CodeStyleSettingPage';
- static const String item_style_setting = 'ItemStyleSettingPage';
- static const String version_info = 'VersionInfo';
- static const String login = 'login';
-
- static const String category_show = 'CategoryShow';
- static const String issues_point = 'IssuesPointPage';
-
- static const String attr = 'AttrUnitPage';
- static const String bug = 'BugUnitPage';
- static const String layout = 'LayoutUnitPage';
- static const String about_me = 'AboutMePage';
- static const String about_app = 'AboutAppPage';
- static const String register = 'register';
-
- static const String data_manage = 'DataManagePage';
-
- static Route generateRoute(RouteSettings settings) {
- switch (settings.name) {
- //
- case UnitRouter.nav:
- if(Platform.isWindows||Platform.isMacOS||Platform.isLinux){
- return NoAnimRouter(child: UnitNavigation());
- }
- return Left2RightRouter(child: UnitNavigation());
-
- // 组件详情页
- case widget_detail:
- Widget child;
- if(Platform.isWindows||Platform.isMacOS||Platform.isLinux){
- child = DeskWidgetDetailPageScope( model: settings.arguments as WidgetModel,
- );
- }else{
- child = WidgetDetailPageScope(
- model: settings.arguments as WidgetModel,
- );
- }
-
- return Right2LeftRouter(
- child: child);
-
- case search:
- return Right2LeftRouter(child: const SearchPageProvider());
- case collect:
- return Right2LeftRouter(child: const CollectPageAdapter());
-
- case setting:
- return Right2LeftRouter(child: const SettingPage());
- case data_manage:
- return Right2LeftRouter(child: const DataManagePage());
- case font_setting:
- return Right2LeftRouter(child: const FontSettingPage());
- case theme_color_setting:
- return Right2LeftRouter(child: const ThemeColorSettingPage());
- case code_style_setting:
- return Right2LeftRouter(child: const CodeStyleSettingPage());
- case item_style_setting:
- return Right2LeftRouter(child: const ItemStyleSettingPage());
-
- case version_info:
- return Right2LeftRouter(child: const VersionInfo());
-
- case issues_point:
- return Right2LeftRouter(child: const IssuesPointScope());
- case login:
- return Right2LeftRouter(child: const LoginPage());
-
- case register:
- return Right2LeftRouter(child: const RegisterPage());
-
- case attr:
- return Right2LeftRouter(child: const AttrUnitPage());
- case bug:
- return Right2LeftRouter(child: const BugUnitPage());
- case layout:
- return Right2LeftRouter(child: const LayoutUnitPage());
- case about_app:
- return Right2LeftRouter(child: const AboutAppPage());
- case about_me:
- return Right2LeftRouter(child: const AboutMePage());
-
- case point_detail:
- return Right2LeftRouter(child: const IssuesDetailPage());
-
- case category_show:
- return Right2LeftRouter(
- child: CategoryShow(
- model: settings.arguments as CategoryModel,
- ));
-
- default:
- return MaterialPageRoute(
- builder: (_) => Scaffold(
- body: Center(
- child: Text('No route defined for ${settings.name}'),
- ),
- ));
- }
- }
-}
diff --git a/lib/app/utils/Toast.dart b/lib/app/utils/Toast.dart
deleted file mode 100644
index 2f174108..00000000
--- a/lib/app/utils/Toast.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// import 'package:flutter/material.dart';
-//
-// class Toast {
-// static toast(BuildContext context, String msg,
-// {duration = const Duration(milliseconds: 600),
-// Color? color,
-// SnackBarAction? action}) {
-//
-// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
-// content: Text(msg),
-// duration: duration,
-// action: action,
-// backgroundColor: color??Theme.of(context).primaryColor,
-// ));
-// }
-//
-// static void error(BuildContext context,String msg){
-// toast(context,msg, color:Colors.red, );
-// }
-//
-// static void warning(BuildContext context,String msg){
-// toast(context,msg, color:Colors.orange, );
-// }
-//
-// static void success(BuildContext context,String msg){
-// toast(context,msg, color:Theme.of(context).primaryColor, );
-// }
-//
-// static void green(BuildContext context,String msg){
-// toast(context,msg, color:Colors.green, );
-// }
-// }
diff --git a/lib/app/utils/color_utils.dart b/lib/app/utils/color_utils.dart
deleted file mode 100644
index 3e245dd4..00000000
--- a/lib/app/utils/color_utils.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-import 'dart:math';
-
-import 'package:flutter/material.dart';
-
-import 'random_provider.dart';
-
-
-
-class ColorUtils {
- static Color randomColor({
- int limitA = 120,
- int limitR = 0,
- int limitG = 0,
- int limitB = 0,
- }) {
- Random random = RandomProvider.random;
- int a = limitA + random.nextInt(256 - limitA); //透明度值
- int r = limitR + random.nextInt(256 - limitR); //红值
- int g = limitG + random.nextInt(256 - limitG); //绿值
- int b = limitB + random.nextInt(256 - limitB); //蓝值
- return Color.fromARGB(a, r, g, b); //生成argb模式的颜色
- }
-
-
- /// 使用方法:
- /// var color1=ColorUtils.parse("#33428A43");
- /// var color2=ColorUtils.parse("33428A43");
- /// var color3=ColorUtils.parse("#428A43");
- ///var color4=ColorUtils.parse("428A43");
- ///
- static Color parse(String code) {
- Color result =Colors.red;
- int value = 0 ;
- if (code.contains("#")) {
- try {
- value = int.parse(code.substring(1), radix: 16);
- } catch (e) {
- print(e);
- }
- switch (code.length) {
- case 1 + 6://6位
- result = Color(value + 0xFF000000);
- break;
- case 1 + 8://8位
- result = Color(value);
- break;
- default:
- result =Colors.red;
- }
- }else {
- try {
- value = int.parse(code, radix: 16);
- } catch (e) {
- print(e);
- }
- switch (code.length) {
- case 6:
- result = Color(value + 0xFF000000);
- break;
- case 8:
- result = Color(value);
- break;
- default:
- result =Colors.red;
- }
- }
- return result;
- }
-
- static String colorString(Color color) =>
- "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
-}
-
diff --git a/lib/app/utils/convert.dart b/lib/app/utils/convert.dart
deleted file mode 100644
index 711d1dad..00000000
--- a/lib/app/utils/convert.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-
-import 'package:db_storage/db_storage.dart';
-import 'package:flutter_unit/painter_system/gallery_factory.dart';
-import 'package:widget_repository/widget_repository.dart';
-
-/// create by 张风捷特烈 on 2020-03-07
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class Convert {
- static WidgetFamily toFamily(int id) {
- switch (id) {
- case 0:
- return WidgetFamily.statelessWidget;
- case 1:
- return WidgetFamily.statefulWidget;
- case 2:
- return WidgetFamily.singleChildRenderObjectWidget;
- case 3:
- return WidgetFamily.multiChildRenderObjectWidget;
- case 4:
- return WidgetFamily.sliver;
- case 5:
- return WidgetFamily.proxyWidget;
- case 6:
- return WidgetFamily.other;
- default:
- return WidgetFamily.statelessWidget;
- }
- }
-
- static Map galleryTypeMap = {
- GalleryType.base: "基础绘制",
- GalleryType.fun: "趣味绘制",
- GalleryType.particle: "粒子绘制",
- GalleryType.anim: "动画手势",
- GalleryType.art: "艺术画廊",
- };
-
- static String convertFileSize(int size){
- double result = size / 1024.0;
- if(result<1024){
- return "${result.toStringAsFixed(2)} Kb";
- }else if(result>1024&&result<1024*1024){
- return "${(result/1024).toStringAsFixed(2)} Mb";
- }else{
- return "${(result/1024/1024).toStringAsFixed(2)} Gb";
- }
- }
-
-
-}
diff --git a/lib/app/utils/toly_utils.dart b/lib/app/utils/toly_utils.dart
deleted file mode 100644
index ea48a992..00000000
--- a/lib/app/utils/toly_utils.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-library toly_utils;
-export 'color_utils.dart';
-export 'random_provider.dart';
diff --git a/lib/app/views/about/version/version_shower.dart b/lib/app/views/about/version/version_shower.dart
deleted file mode 100644
index 3c20a2cd..00000000
--- a/lib/app/views/about/version/version_shower.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:package_info_plus/package_info_plus.dart';
-
-class VersionShower extends StatefulWidget {
- const VersionShower({Key? key}) : super(key: key);
-
- @override
- _VersionShowerState createState() => _VersionShowerState();
-}
-
-class _VersionShowerState extends State {
- String version = '1.0.0';
-
- @override
- void initState() {
- super.initState();
- _fetchVersion();
- }
-
- @override
- Widget build(BuildContext context) {
- return Text('Version $version');
- }
-
- void _fetchVersion() async{
- PackageInfo packageInfo = await PackageInfo.fromPlatform();
- if(mounted) {
- setState(() {
- version= packageInfo.version;
- });
- }
- }
-}
diff --git a/lib/app/views/data_manage/data_manage_page.dart b/lib/app/views/data_manage/data_manage_page.dart
deleted file mode 100644
index 95662317..00000000
--- a/lib/app/views/data_manage/data_manage_page.dart
+++ /dev/null
@@ -1,149 +0,0 @@
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:app_config/app_config.dart';
-import 'package:db_storage/db_storage.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:flutter_unit/app/utils/Toast.dart';
-import 'package:flutter_unit/point_system/api/category_api.dart';
-
-import 'package:authentication/views/authentic_widget.dart';
-import 'package:utils/utils.dart';
-import 'package:widget_module/blocs/blocs.dart';
-
-import 'package:path/path.dart' as path;
-import 'package:sqflite/sqflite.dart';
-import 'package:widget_repository/widget_repository.dart';
-
-/// create by 张风捷特烈 on 2021/2/26
-/// contact me by email 1981462002@qq.com
-/// 说明:
-///
-
-class DataManagePage extends StatelessWidget {
- const DataManagePage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: const Text('数据管理'),
- ),
- body: Builder(
- builder: (ctx) => ListView(
- children: [
- AuthenticWidget.just(
- ListTile(
- trailing: Icon(
- TolyIcon.upload,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('备份收藏集数据'),
- onTap: () => _doUploadCategoryData(ctx),
- ),
- ),
- AuthenticWidget.just(const Divider()),
- AuthenticWidget.just(ListTile(
- trailing: Icon(
- TolyIcon.download,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('同步收藏集数据'),
- onTap: () => _doSync(ctx),
- )),
- AuthenticWidget.just(const Divider()),
- ListTile(
- trailing: Icon(
- Icons.refresh,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('收藏集数据重置'),
- // trailing: _nextIcon(context),
- onTap: () => _recallDatabase(ctx),
- ),
- const Divider(),
- ],
- ),
- ),
- );
- }
-
- _recallDatabase(BuildContext context) async {
- String databasesPath = await getDatabasesPath();
- String dbPath = path.join(databasesPath, "flutter.db");
- ByteData data = await rootBundle.load(path.join("assets", "flutter.db"));
- List bytes =
- data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
- await File(dbPath).writeAsBytes(bytes, flush: true);
- print("==== debug ===== assets ======拷贝完成====");
- BlocProvider.of(context).add(const EventLoadCategory());
- BlocProvider.of(context).add(const EventLoadLikeData());
- Toast.toast(context, '重置成功!');
- }
-
- void _doUploadCategoryData(BuildContext context) async {
- CategoryRepository rep = BlocProvider.of(context).repository;
- List loadCategories = await rep.loadCategoryData();
-
- List likeData = await LocalDb.instance.likeDao.likeWidgetIds();
-
- String json = jsonEncode(loadCategories);
- String likeJson = jsonEncode(likeData);
-
- TaskResult result =
- await CategoryApi.uploadCategoryData(data: json, likeData: likeJson);
-
- if (result.success) {
- Toast.toast(context, '数据集备份成功!');
- } else {
- Toast.toast(context, '数据集备份失败!');
- }
- }
-
- void _doSync(BuildContext context) async {
- TaskResult result = await CategoryApi.getCategoryData();
-
- if (result.success) {
- // 说明请求成功
- if (result.data != null) {
- //说明有后台备份数据,进行同步操作
- CategoryRepository repository =
- BlocProvider.of(context).repository;
- await repository.syncCategoryByData(
- result.data!.data, result.data!.likeData);
- BlocProvider.of(context).add(const EventLoadCategory());
- BlocProvider.of(context).add(const EventLoadLikeData());
- } else {
- // 说明还没有后台数据,
- // 这里防止有傻孩子没点备份,就点同步,哥哥好心,给备份一下。
- CategoryRepository rep =
- BlocProvider.of(context).repository;
- List loadCategories = await rep.loadCategoryData();
- List likeData = await LocalDb.instance.likeDao.likeWidgetIds();
-
- String json = jsonEncode(loadCategories);
- String likeJson = jsonEncode(likeData);
- await CategoryApi.uploadCategoryData(data: json, likeData: likeJson);
- }
- Toast.toast(context, '数据同步份成功!');
- } else {
- Toast.toast(context, '数据同步份失败!');
- }
- }
-}
-
-// class LoadingIndicate extends StatefulWidget {
-// Future Function task;
-// @override
-// _LoadingIndicateState createState() => _LoadingIndicateState();
-// }
-//
-// class _LoadingIndicateState extends State {
-// @override
-// Widget build(BuildContext context) {
-// return Container();
-// }
-// }
diff --git a/lib/app/views/setting/app_style_setting.dart b/lib/app/views/setting/app_style_setting.dart
deleted file mode 100644
index bd2e9445..00000000
--- a/lib/app/views/setting/app_style_setting.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-/// create by 张风捷特烈 on 2020-04-10
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-
-void showAppStyleSelectDialog(BuildContext context) {
- List data = Cons.kAppStyleStringMap.values.toList();
- showCupertinoModalPopup(
- context: context,
- builder: (context) => AppThemeSettingDialog(
- data: data,
- ));
-}
-
-class AppThemeSettingDialog extends StatelessWidget {
- final List data;
-
-
- const AppThemeSettingDialog({Key? key,required this.data}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Material(
- child: SizedBox(
- height: 350,
- width: MediaQuery.of(context).size.width,
- child: Column(
- children: [
- const Padding(
- padding: EdgeInsets.all(16.0),
- child: Text(
- '选择应用风格样式',
- style:
- TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
- ),
- ),
- const Divider(height: 1,),
- Expanded(
- child: ListView.builder(
- padding: EdgeInsets.zero,
- itemBuilder: _buildItem,
- itemCount: data.length,
- ),
- )
- ],
- ),
- // color: Colors.orange,
- ),
- );
- }
-
- Widget _buildItem(BuildContext context, int index) {
- AppStyle locale = Cons.kAppStyleStringMap.keys.toList()[index];
- AppStyle style = BlocProvider.of(context).state.appStyle;
- bool checked = style == locale;
- Color color = Theme.of(context).primaryColor;
- return ListTile(
- title: Text(data[index]),
- onTap: () => _onSelect(context, index),
- trailing: checked ? Icon(Icons.check, size: 20, color: color) : null,
- );
- }
- void _onSelect(BuildContext context, int index) {
- AppStyle appStyle = Cons.kAppStyleStringMap.keys.toList()[index];
- BlocProvider.of(context).changeAppStyle(appStyle);
- Navigator.of(context).pop();
- }
-}
diff --git a/lib/app/views/setting/font_setting.dart b/lib/app/views/setting/font_setting.dart
deleted file mode 100644
index cea5e08f..00000000
--- a/lib/app/views/setting/font_setting.dart
+++ /dev/null
@@ -1,79 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:components/components.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-
-/// create by 张风捷特烈 on 2020-04-10
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class FontSettingPage extends StatelessWidget {
- const FontSettingPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: UnitColor.scaffoldBgLight,
- appBar: const UnitAppbar(title: '字体设置 - font setting'),
- body: BlocBuilder(
- builder: (_, state) => _buildFontCell(
- context, Cons.kFontFamilySupport, state.fontFamily)),
- );
- }
-
- Widget _buildFontCell(
- BuildContext context, List fontFamilySupport, String fontFamily) {
- return GridView.count(
- padding: const EdgeInsets.only(top: 20, left: 10, right: 10),
- shrinkWrap: true,
- crossAxisCount: 2,
- mainAxisSpacing: 10,
- crossAxisSpacing: 10,
- childAspectRatio: 1.5,
- children: fontFamilySupport
- .map((e) => FeedbackWidget(
- a: 0.95,
- duration: const Duration(milliseconds: 200),
- onPressed: () {
- BlocProvider.of(context).switchFontFamily(e);
- },
- child: Card(
- child: GridTile(
- header: Container(
- padding: const EdgeInsets.only(left: 10, right: 5),
- height: 30,
- color: fontFamily == e
- ? Colors.blue.withAlpha(88)
- : Colors.grey.withAlpha(88),
- child: Row(
- children: [
- Text(e,
- style: TextStyle(
- color: Colors.black,
- fontFamily: e,
- )),
- const Spacer(),
- if (fontFamily == e) Circle(color: Theme.of(context).primaryColor,)
- ],
- ),
- ),
- child: Container(
- decoration: BoxDecoration(
- gradient: LinearGradient(colors: [
- Colors.blueAccent.withAlpha(22),
- Colors.blueAccent.withAlpha(22),
- Theme.of(context).primaryColor.withAlpha(88)
- ])),
- alignment: const Alignment(0, 0.4),
- child: Text(
- '张风捷特烈\n@toly1994',
- style: TextStyle(fontFamily: e, fontSize: 16),
- )),
- ),
- )))
- .toList(),
- );
- }
-}
diff --git a/lib/app/views/setting/item_style_setting.dart b/lib/app/views/setting/item_style_setting.dart
deleted file mode 100644
index f543aadb..00000000
--- a/lib/app/views/setting/item_style_setting.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:components/components.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:old_fancy_mobile_ui/old_fancy_mobile_ui.dart';
-
-/// create by 张风捷特烈 on 2020-04-10
-/// contact me by email 1981462002@qq.com
-/// 说明: item样式切换支持
-
-class ItemStyleSettingPage extends StatelessWidget {
- const ItemStyleSettingPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: UnitColor.scaffoldBgLight,
- appBar: const UnitAppbar(title: 'item样式设置'),
- body: BlocBuilder(builder: (_, state) {
- return _buildCell(context, state.itemStyleIndex);
- }),
- );
- }
-
- List get items=> HomeItemSupport.itemSimples();
-
- Widget _buildCell(BuildContext context, int index) {
- return ListView.builder(
- itemCount: items.length,
- itemBuilder: (_, i) => Padding(
- padding: const EdgeInsets.only(bottom: 8,left: 8,right: 8),
- child: FeedbackWidget(
- a: 0.95,
- duration: const Duration(milliseconds: 200),
- onPressed: () {
- BlocProvider.of(context).changeItemStyle(i);
- },
- child: Stack(
- children: [
- items[i],
- if (index == i)
- Positioned(
- left: 25,
- top: 15,
- child: Circle(
- color: Theme.of(context).primaryColor,
- radius: 10,
- child: const Icon(
- Icons.check,
- color: Colors.white,
- size: 15,
- ),
- ),
- )
- ],
- )),
- ));
- }
-}
diff --git a/lib/app/views/setting/setting_page.dart b/lib/app/views/setting/setting_page.dart
deleted file mode 100644
index 0190342c..00000000
--- a/lib/app/views/setting/setting_page.dart
+++ /dev/null
@@ -1,169 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:components/components.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/app/navigation/overlay_tool_wrapper.dart';
-
-
-import 'app_style_setting.dart';
-
-class SettingPage extends StatelessWidget {
-
- const SettingPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- const Widget divider = Divider(height: 1);
-
- return Scaffold(
- backgroundColor: Colors.white,
- appBar: const UnitAppbar(title:'应用设置'),
- body: ListView(
- children: [
- Container( height: 15,color: UnitColor.scaffoldBgLight),
-
- ListTile(
- leading: Icon(
- Icons.style,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('应用整体风格', style: TextStyle(fontSize: 16)),
- subtitle: BlocBuilder(
- builder: (_,state)=>Text(
- Cons.kAppStyleStringMap[state.appStyle]!
- , style: const TextStyle(fontSize: 14)
- ),
- ),
- onTap: (){
- showAppStyleSelectDialog(context);
- },
- ),
- divider,
- ListTile(
- leading: Icon(
- Icons.palette,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('主题色设置', style: TextStyle(fontSize: 16)),
- subtitle: BlocBuilder(
- builder: (_,state)=>Text(
- Cons.kThemeColorSupport[state.themeColor]!,
- style: TextStyle(color: state.themeColor,fontSize: 14),
- ),
- ),
- trailing: _nextIcon(context),
- onTap: () => Navigator.of(context).pushNamed(UnitRouter.theme_color_setting),
- ),
- divider,
- ListTile(
- leading: Icon(
- Icons.translate,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('字体设置', style: TextStyle(fontSize: 16)),
- subtitle: BlocBuilder(
- builder: (_,state)=>Text(
- state.fontFamily
- ),
- ),
- trailing: _nextIcon(context),
- onTap: () => Navigator.of(context).pushNamed(UnitRouter.font_setting),
- ),
- divider,
- Container( height: 10,color: UnitColor.scaffoldBgLight),
- ListTile(
- leading: Icon(
- TolyIcon.icon_item,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('条目样式设置', style: TextStyle(fontSize: 16),),
- subtitle: const Text('仅华丽样式下可用',style:TextStyle(fontSize: 14),),
- trailing: _nextIcon(context),
- onTap: () => Navigator.of(context).pushNamed(UnitRouter.item_style_setting),
- ),
- divider,
- ListTile(
- leading: Icon(
- TolyIcon.icon_code,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('代码高亮样式', style: TextStyle(fontSize: 16)),
- trailing: _nextIcon(context),
- onTap: () => Navigator.of(context).pushNamed(UnitRouter.code_style_setting),
- ),
- divider,
- Container( height: 10,color: UnitColor.scaffoldBgLight),
- _buildShowBg(context),
- divider,
- _buildShowOver(context),
- divider,
- // _buildShowTool(context),
- // divider,
- Container( height: 10,color: UnitColor.scaffoldBgLight),
- ListTile(
- leading: Icon(
- Icons.info,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('版本信息', style: TextStyle(fontSize: 16)),
- trailing: _nextIcon(context),
- onTap: () => Navigator.of(context).pushNamed(UnitRouter.version_info),
- ),
- ],
- ),
- );
- }
-
-
-
- Widget _buildShowBg(BuildContext context) =>
- BlocBuilder(
- builder: (_, state) => SwitchListTile(
- value: state.showBackGround,
- secondary: Icon(
- TolyIcon.icon_background,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('显示背景', style: TextStyle(fontSize: 16)),
- onChanged: (show) {
- BlocProvider.of(context).switchShowBg(show);
- },
- ));
-
- Widget _buildShowOver(BuildContext context) =>
- BlocBuilder(
- builder: (_, state) => SwitchListTile(
- value: state.showPerformanceOverlay,
- secondary: Icon(
- TolyIcon.icon_show,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('显示性能浮层', style: TextStyle(fontSize: 16)),
- onChanged: (show) {
- BlocProvider.of(context).switchShowOver(show);
- },
- ));
-
- Widget _buildShowTool(BuildContext context) =>
- BlocBuilder(
- builder: (_, state) => SwitchListTile(
- value: state.showOverlayTool,
- secondary: Icon(
- TolyIcon.icon_layout,
- color: Theme.of(context).primaryColor,
- ),
- title: const Text('显示浮动工具', style: TextStyle(fontSize: 16)),
- onChanged: (show) {
- if(show){
- OverlayToolWrapper.of(context).showFloating();
- }else{
- OverlayToolWrapper.of(context).hideFloating();
- }
- BlocProvider.of(context).switchShowTool(show);
- },
- ));
-
-
- Widget _nextIcon(BuildContext context) =>
- Icon(Icons.chevron_right, color: Theme.of(context).primaryColor);
-}
diff --git a/lib/app/views/setting/theme_color_setting.dart b/lib/app/views/setting/theme_color_setting.dart
deleted file mode 100644
index a917d743..00000000
--- a/lib/app/views/setting/theme_color_setting.dart
+++ /dev/null
@@ -1,93 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:components/components.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-
-/// create by 张风捷特烈 on 2020-04-10
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class ThemeColorSettingPage extends StatelessWidget {
- const ThemeColorSettingPage({Key? key}) : super(key: key);
-
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: UnitColor.scaffoldBgLight,
- appBar: const UnitAppbar(title:'主题色设置'),
- body: BlocBuilder(
- builder: (_, state) => _buildCell(
- context, Cons.kThemeColorSupport.keys.toList(), state.themeColor)),
- );
- }
-
- Widget _buildCell(
- BuildContext context, List themeColorSupport, MaterialColor color) {
- return GridView.count(
- padding: const EdgeInsets.only(top: 20, left: 10, right: 10),
- shrinkWrap: true,
- crossAxisCount: 2,
- mainAxisSpacing: 10,
- crossAxisSpacing: 10,
- childAspectRatio: 1.5,
- children: themeColorSupport
- .map((MaterialColor c) => FeedbackWidget(
- a: 0.95,
- duration: const Duration(milliseconds: 200),
- onPressed: () => BlocProvider.of(context).switchThemeColor(c),
- child: GridTile(
- header: Container(
- decoration: BoxDecoration(
- borderRadius: const BorderRadius.only(topLeft: Radius.circular(10),topRight: Radius.circular(10)),
- color: color == c
- ? Colors.blue.withAlpha(88):
- Colors.grey.withAlpha(55),
- ),
- padding: const EdgeInsets.only(left: 10, right: 5),
- height: 30,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- const Spacer(),
- Text(colorString(c),
- style: const TextStyle(
- color: Colors.white,
- )),
- const Spacer(),
- if (color == c) const Padding(
- padding: EdgeInsets.only(right:8.0),
- child: Circle(color: Colors.white,radius: 7,),
- )
- ],
- ),
- ),
- child: Container(
- decoration: BoxDecoration(
- borderRadius: const BorderRadius.all(Radius.circular(10)),
- gradient: LinearGradient(colors: [
- c.shade50,
- c.shade100,
- c.shade200,
- c.shade300,
- c.shade400,
- c.shade500,
- c.shade600,
- c.shade700,
- c.shade800,
- c.shade900,
- ])),
- alignment: const Alignment(0,0.35),
- child: Text(
- '${Cons.kThemeColorSupport[c]}',
- style: const TextStyle(fontSize: 18,color: Colors.white,fontWeight: FontWeight.bold),
- )),
- )))
- .toList(),
- );
- }
-
- String colorString(Color color) =>
- "#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}";
-}
diff --git a/lib/app/views/splash/standard_unit_splash.dart b/lib/app/views/splash/standard_unit_splash.dart
deleted file mode 100644
index 44308f8a..00000000
--- a/lib/app/views/splash/standard_unit_splash.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-import 'dart:math';
-
-import 'package:app_config/app_config.dart';
-import 'package:db_storage/db_storage.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:old_fancy_mobile_ui/old_fancy_mobile_ui.dart';
-import 'package:utils/utils.dart';
-
-import 'package:widget_module/blocs/blocs.dart';
-
-import 'dart:ui' as ui;
-
-import 'package:widget_repository/widget_repository.dart';
-
-/// create by 张风捷特烈 on 2020-03-07
-/// contact me by email 1981462002@qq.com
-/// 说明: app 闪屏页
-
-class StandardUnitSplash extends StatefulWidget {
- const StandardUnitSplash({Key? key}) : super(key: key);
-
- @override
- _StandardUnitSplashState createState() => _StandardUnitSplashState();
-}
-
-class _StandardUnitSplashState extends State
- with TickerProviderStateMixin {
- static const int _minCost = 1500;
-
- int _recorder = 0;
-
- final Paint paint = Paint()
- ..style = PaintingStyle.stroke
- ..shader = ui.Gradient.linear(
- const Offset(0, 0),
- const Offset(22, 0),
- [Colors.red, Colors.yellow, Colors.blue, Colors.green],
- [1 / 4, 2 / 4, 3 / 4, 1],
- TileMode.mirror,
- Matrix4.rotationZ(pi / 4).storage,
- );
-
- @override
- void initState() {
- super.initState();
- _recorder = DateTime.now().millisecondsSinceEpoch;
- }
-
- @override
- Widget build(BuildContext context) {
- final Size winSize = MediaQuery.of(context).size;
- return AnnotatedRegion(
- value: const SystemUiOverlayStyle(
- statusBarColor: Colors.transparent,
- statusBarIconBrightness: Brightness.dark),
- child: Material(
- child: BlocListener(
- listener: _listenStart,
- child: Column(
- children: [
- const Spacer(),
- Expanded(
- child: Wrap(
- direction: Axis.vertical,
- alignment: WrapAlignment.center,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: [
- Stack(
- children: [
- Text(
- "U",
- style: TextStyle(
- fontSize: 26,
- height: 1,
- fontWeight: FontWeight.bold,
- foreground: paint),
- ),
- const FlutterLogo(size: 60),
- ],
- ),
- const SizedBox(
- height: 20,
- ),
- _buildFlutterUnitText(winSize.height, winSize.width),
- ],
- )),
- Expanded(
- child: Stack(
- alignment: Alignment.bottomCenter,
- children: [
- Positioned(
- bottom: 15,
- child: Wrap(
- direction: Axis.vertical,
- alignment: WrapAlignment.center,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: const [
- Text("Power By 张风捷特烈",
- style: UnitTextStyle.splashShadows),
- Text("· 2021 · @编程之王 ",
- style: UnitTextStyle.splashShadows),
- ],
- )),
- ],
- ))
- ],
- )),
- ),
- );
- }
-
- Widget _buildFlutterUnitText(double winH, double winW) {
- return FlutterUnitText(
- text: StrUnit.appName,
- color: Theme.of(context).primaryColor,
- );
- }
-
- // 监听资源加载完毕,启动,触发事件
- void _listenStart(BuildContext context, AppState state) {
- HttpUtil.instance.rebase(PathUnit.baseUrl);
- int cost = DateTime.now().millisecondsSinceEpoch - _recorder;
- BlocProvider.of(context)
- .add(const EventTabTap(WidgetFamily.statelessWidget));
- BlocProvider.of(context).add(const EventLoadLikeData());
- BlocProvider.of(context).add(const EventLoadCategory());
-
- // 启动耗时小于 _minCost 时,等待 delay 毫秒
- int delay = cost < _minCost ? _minCost - cost : 0;
- Future.delayed(Duration(milliseconds: delay)).then((value) {
- Navigator.of(context).pushReplacementNamed(UnitRouter.nav);
- });
- }
-}
diff --git a/lib/code_gen/bloc/state.dart b/lib/code_gen/bloc/state.dart
deleted file mode 100644
index e7bac1b9..00000000
--- a/lib/code_gen/bloc/state.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/code_gen/model/class.dart';
-
-class ClassGenBloc extends Cubit{
-
- ClassGenBloc():super(Class(fields: [], name: ''));
-
-
-
-}
\ No newline at end of file
diff --git a/lib/code_gen/desk_widget_top_bar.dart b/lib/code_gen/desk_widget_top_bar.dart
deleted file mode 100644
index ae4e3de4..00000000
--- a/lib/code_gen/desk_widget_top_bar.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_unit/app/plateform_adapter/window/windows_adapter.dart';
-
-import '../widget_ui/desk_ui/widget_panel/window_buttons.dart';
-
-
-
-class DeskCodeGenTopBar extends StatefulWidget {
- final ValueChanged onTabPressed;
- final VoidCallback onTapGen;
-
- const DeskCodeGenTopBar({Key? key,required this.onTabPressed, required this.onTapGen}) : super(key: key);
-
- @override
- State createState() => _DeskCodeGenTopBarState();
-}
-
-class _DeskCodeGenTopBarState extends State with SingleTickerProviderStateMixin {
- late TabController tabController;
-
- static const List _tabs = ['IconFont', '数据类' , '状态管理', 'Json 解析',];
-
- @override
- void initState() {
- super.initState();
- tabController = TabController(length: _tabs.length, vsync: this);
- }
-
- @override
- Widget build(BuildContext context) {
- Color themeColor = Theme.of(context).primaryColor;
-
- return DragToMoveAreaNoDouble(
- child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- height: 64,
- color: Colors.white,
- child: Row(
- children: [
- SizedBox(
- width: 350,
- child: TabBar(
- onTap: widget.onTabPressed,
- indicatorSize: TabBarIndicatorSize.label,
- labelPadding: const EdgeInsets.symmetric(horizontal: 6),
- isScrollable: false,
- indicator: RoundRectTabIndicator(
- borderSide: BorderSide(color: themeColor, width: 3),
- ),
- labelStyle: const TextStyle(
- fontSize: 14,
- fontWeight: FontWeight.bold,
- ),
- controller: tabController,
- labelColor: themeColor,
- indicatorWeight: 3,
- unselectedLabelColor: Colors.grey,
- indicatorColor: themeColor,
- tabs:
- _tabs.map((String name) => Tab(text: name)).toList(),
- ),
- ),
- Spacer(),
-
- const SizedBox(width: 20,),
- WindowButtons(),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/code_gen/icon_font_gen/gen_message_action.dart b/lib/code_gen/icon_font_gen/gen_message_action.dart
deleted file mode 100644
index 8059423e..00000000
--- a/lib/code_gen/icon_font_gen/gen_message_action.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-
-
-
-class GenMessageAction extends StatelessWidget {
- final VoidCallback onGen;
- const GenMessageAction({Key? key, required this.onGen}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(child: Text(
- '使用方式:\n1. 在 iconfont.cn 挑选图标,加入项目,下载压缩包。\n2. 选择 Flutter 项目地址,配置资源、产物文件位置。\n3. 点击生成代码按钮,即可生成相关代码。',
- style: TextStyle(
- color: Theme.of(context).primaryColor,fontWeight: FontWeight.bold),)),
- ElevatedButton(
- style: ElevatedButton.styleFrom(
- elevation: 0,
- shape: const StadiumBorder()
- ),
- onPressed:onGen, child: Wrap(
- crossAxisAlignment: WrapCrossAlignment.center,
- spacing: 4,
- children: [
- Icon(TolyIcon.icon_fast,size: 16,),
- const Text('生成代码',style: TextStyle(height: 1,fontSize: 12),),
- ],
- )),
- ],
- );
- }
-}
diff --git a/lib/code_gen/icon_font_gen/icon_font_class_parser.dart b/lib/code_gen/icon_font_gen/icon_font_class_parser.dart
deleted file mode 100644
index 9faa67ae..00000000
--- a/lib/code_gen/icon_font_gen/icon_font_class_parser.dart
+++ /dev/null
@@ -1,148 +0,0 @@
-import 'dart:convert';
-import 'dart:io';
-import 'package:archive/archive_io.dart';
-
-import 'icon_font_gen_config.dart';
-import 'package:path/path.dart' as path;
-
-class IconFontClassParser{
-
- void gen(IconFontGenConfig config){
- final inputStream = InputFileStream(config.srcZip);
- // 将压缩包有用资源解压到目标文件
- final archive = ZipDecoder().decodeBuffer(inputStream);
- for (var file in archive.files) {
- if (file.isFile) {
- if (file.name.endsWith('.ttf')) {
- final outputStream = OutputFileStream(config.ttfDistPath);
- file.writeContent(outputStream);
- outputStream.close();
- }
- if (file.name.endsWith('.json')) {
- dynamic data = file.content;
- String jsonContent = utf8.decode(data);
- String resultCode = parser(jsonContent,config.fontFamily);
- File distFile = File(config.distFilePath);
- if(!distFile.existsSync()){
- distFile.createSync(recursive: true);
- }
- distFile.writeAsStringSync(resultCode);
- setYaml(config);
- }
- }
- }
- }
-
- String parser(String input,String fontFamily){
- dynamic map = json.decode(input);
- List glyphs = map['glyphs'] as List;
- String code = '';
- for(int i=0;i lines = pubspecFile.readAsLinesSync();
-
- RegExp fontsRegex = RegExp(r'^ fonts:',multiLine: true);
- bool hasFonts = fontsRegex.hasMatch(lines.join('\n'));
-
- if(!hasFonts){
- // 当前没有 fonts 节点,需要添加到 flutter 节点下
- int index = lines.indexWhere((e) => e.startsWith('flutter:'));
- List fonts = [
- ' fonts:',
- ' - family: $familyName',
- ' fonts:',
- ' - asset: $fontAssetsDist',
- ];
-
- lines.insertAll(index+1, fonts);
- pubspecFile.writeAsStringSync(lines.join('\n'));
- return;
- }
- // 存在 fonts 节点,查询 family ,有没有当前字体图标
- bool hasTargetFamily = false;
- RegExp regExp = RegExp(r'^ +- family: +(\w+)');
-
- for(int i=0;i e.startsWith(fontsRegex));
- List fonts = [
- ' - family: $familyName',
- ' fonts:',
- ' - asset: $fontAssetsDist',
- ];
- lines.insertAll(index+1, fonts);
- pubspecFile.writeAsStringSync(lines.join('\n'));
- return;
- }
- }
-
- // // 修改 pubspec.yaml
- // void setYaml(IconFontGenConfig config){
- // String fontFamily = config.fontFamily;
- // String assets = config.assetsDist.replaceAll('\\', '/');
- //
- // final String filePath = path.join(config.projectPath,'pubspec.yaml');
- // File pubspecFile = File(filePath);
- // final String pubspec = pubspecFile.readAsStringSync();
- // final doc = loadYaml(pubspec);
- // final modifiableDoc = getModifiableNode(doc);
- //
- // YamlList? fontsList = doc['flutter']['fonts'] as YamlList?;
- // if(fontsList == null){
- // // 新文件,没有配置 fonts 节点
- // modifiableDoc['flutter']['fonts'] = YamlMap.wrap({
- // 'family': fontFamily,
- // 'fonts':YamlList.wrap([YamlMap.wrap({'asset':'$assets/iconfont.ttf'})])
- // });
- // }else{
- // final modifiableList = getModifiableNode(fontsList);
- // modifiableList.removeWhere((e) => e['family'] == fontFamily);
- // modifiableList.add(
- // YamlMap.wrap({
- // 'family': fontFamily,
- // 'fonts':YamlList.wrap([YamlMap.wrap({'asset':'$assets/iconfont.ttf'})])
- // })
- // );
- // modifiableDoc['flutter']['fonts'] = modifiableList;
- // }
- // final targetYaml = toYamlString(modifiableDoc);
- // pubspecFile.writeAsStringSync(targetYaml);
- // }
-
-}
\ No newline at end of file
diff --git a/lib/components/top_bar/desk_simple_top_bar.dart b/lib/components/top_bar/desk_simple_top_bar.dart
deleted file mode 100644
index f13766b8..00000000
--- a/lib/components/top_bar/desk_simple_top_bar.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-import 'package:flutter/material.dart';
-
-import '../../app/plateform_adapter/window/windows_adapter.dart';
-import '../../widget_ui/desk_ui/widget_panel/window_buttons.dart';
-
-class SimpleDeskTopBar extends StatelessWidget {
- final Widget? leading;
-
- const SimpleDeskTopBar({super.key, this.leading});
-
- @override
- Widget build(BuildContext context) {
- return DragToMoveAreaNoDouble(
- child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- height: 64,
- color: Colors.white,
- child: Row(
- children: [
- if (leading != null) leading!,
- const Spacer(),
- const SizedBox(
- width: 20,
- ),
- const WindowButtons(),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/main.dart b/lib/main.dart
index 289530cb..44222857 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,16 +1,3 @@
-import 'package:flutter/gestures.dart';
-import 'package:flutter/material.dart';
-
-import 'app/plateform_adapter/window/windows_adapter.dart';
-import 'app/bloc_wrapper.dart';
-import 'app/flutter_unit.dart';
-
-
-void main() {
- WidgetsFlutterBinding.ensureInitialized();
- //滚动性能优化 1.22.0
- GestureBinding.instance.resamplingEnabled = true;
- runApp(const BlocWrapper(child: FlutterUnit()));
- WindowsAdapter.setSize();
-}
+import 'src/starter/fx_application.dart';
+void main(List args) => const FxApplication().run(args);
diff --git a/lib/painter_system/desk_ui/desk_gallery_unit.dart b/lib/painter_system/desk_ui/desk_gallery_unit.dart
deleted file mode 100644
index 62b582bb..00000000
--- a/lib/painter_system/desk_ui/desk_gallery_unit.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-import 'dart:convert';
-
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-
-import 'package:flutter_unit/painter_system/gallery_card_item.dart';
-import 'package:flutter_unit/painter_system/gallery_factory.dart';
-import 'package:old_fancy_mobile_ui/bloc/color_change_bloc.dart';
-
-import '../../point_system/views/desk_ui/desk_point_page.dart';
-import '../gallery_detail_page.dart';
-
-/// create by 张风捷特烈 on 2020/11/28
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class DeskGalleryUnit extends StatefulWidget {
- const DeskGalleryUnit({Key? key}) : super(key: key);
-
- @override
- _DeskGalleryUnitState createState() => _DeskGalleryUnitState();
-}
-
-class _DeskGalleryUnitState extends State {
- final ValueNotifier factor = ValueNotifier(0);
-
- @override
- void dispose() {
- factor.dispose();
- super.dispose();
- }
-
- final ScrollController controller = ScrollController();
-
- Color get color => BlocProvider.of(context).state.tabColor;
-
- Color get nextColor =>
- BlocProvider.of(context).state.nextTabColor;
-
- BoxDecoration get boxDecoration => const BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(20),
- topRight: Radius.circular(20),
- ),
- );
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: Column(
- children: [
- SimpleDeskTopBar(
- leading: Text(
- 'Flutter 绘制集录',
- style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
- ),
- ),
- Expanded(child: _buildContent()),
- ],
- ),
- );
- }
-
- Widget _buildContent() {
- final List widgets =
- (json.decode(StrUnit.galleryInfo) as List).map((e) {
- GalleryInfo info = GalleryInfo.fromJson(e);
- List children = GalleryFactory.getGalleryByName(info.type);
-
- return FeedbackWidget(
- a: 0.95,
- onPressed: () {
- Navigator.of(context).push(MaterialPageRoute(
- builder: (ctx) => GalleryDetailPage(
- galleryInfo: info,
- children: children,
- )));
- },
- child: GalleryCardItem(
- galleryInfo: info,
- count: children.length,
- ),
- );
- }).toList();
-
- SliverGridDelegate gridDelegate =
- const SliverGridDelegateWithMaxCrossAxisExtent(
- maxCrossAxisExtent: 460,
- mainAxisSpacing: 10,
- mainAxisExtent: 360,
- crossAxisSpacing: 10,
- );
-
- return GridView.builder(
- controller: controller,
- gridDelegate: gridDelegate,
- padding: const EdgeInsets.all(20),
- itemCount: widgets.length,
- itemBuilder: (ctx, index) => widgets[index]);
- }
-}
diff --git a/lib/painter_system/gallery_factory.dart b/lib/painter_system/gallery_factory.dart
deleted file mode 100644
index dbdddfcf..00000000
--- a/lib/painter_system/gallery_factory.dart
+++ /dev/null
@@ -1,270 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_unit/painter_system/anim/spring_widget.dart';
-
-import 'anim/bezier3_player/bezier3_palyer.dart';
-import 'anim/circle_halo.dart';
-import 'anim/curve_shower/curve_anim_shower.dart';
-import 'anim/draw_path.dart';
-import 'anim/dundun_path.dart';
-import 'anim/rotate_by_point/rotate_by_point.dart';
-import 'art/circle_packing.dart';
-import 'art/cubic_disarray.dart';
-import 'art/hypnotic_squares.dart';
-import 'art/joy_division.dart';
-import 'art/piet_mondrian.dart';
-import 'art/tiled_lines.dart';
-import 'art/triangular_mesh.dart';
-import 'art/un_deux_trois.dart';
-import 'base/clock_widget.dart';
-import 'base/digital/digital_shower.dart';
-import 'base/draw_grid_axis.dart';
-import 'base/draw_path_fun.dart';
-import 'base/draw_picture.dart';
-
-import 'base/n_side/n_side_page.dart';
-import 'base/polar/polar_painter_widget.dart';
-import 'base/windmill.dart';
-import 'fun/bufeng/bufeng_panel.dart';
-import 'fun/dundun_view.dart';
-import 'fun/random_portrait.dart';
-import 'fun/stemp/stamp_paper.dart';
-import 'particle/random/random_particle.dart';
-import 'particle/split/particle_split.dart';
-import 'particle/split_img/split_image.dart';
-import 'picture_frame.dart';
-
-/// create by 张风捷特烈 on 2020/12/5
-/// contact me by email 1981462002@qq.com
-/// 说明:
-///
-
-enum GalleryType { base, anim, particle, fun, art }
-
-class GalleryFactory {
- static List getGalleryByName(GalleryType type) {
- switch (type) {
- case GalleryType.base:
- return const [
- FrameShower(
- title: "The Chaos",
- author: "张风捷特烈",
- srcUrl: "/base/draw_picture.dart",
- info: "本样例介绍如何进行图片的绘制:通过加载图片并将图片资源绘制到指定的区域。在上层绘制一批 45° 倾角的栅格线,来练习线条的绘制。",
- content: DrawPicture()),
- FrameShower(
- title: "数字显示管",
- author: "张风捷特烈",
- srcUrl: "/base/digital",
- info: "本样例介绍如何绘制 LED 数字显示管,以此练习对路径 Path 的使用、变换、组合,以及组件封装的知识。是一个非常好的绘制案例。",
- content: DigitalShower()),
- FrameShower(
- title: "旋转风车",
- author: "张风捷特烈",
- srcUrl: "/base/windmill.dart",
- info: "本样例介绍如何进行简单的路径绘制,以及画板的旋转,再结合动画让风车旋转。这是一个非常精简的绘制与动画结合的案例。",
- content: WindmillWidget()),
- FrameShower(
- title: "平面直角坐标系",
- author: "张风捷特烈",
- srcUrl: "/base/draw_grid_axis.dart",
- info:
- "本样例介绍如何使用线路径和文字绘制网格坐标系,并将绘制对象进行封装,方便重用。坐标系也会在绘制时提供参考,入门必备。",
- content: DrawGridAxis()),
- FrameShower(
- title: "平面极坐标系",
- author: "张风捷特烈",
- srcUrl: "/base/polar",
- info:
- "本样例介绍如何使用绘制平面的极坐标系,并根据函数方程收集极坐标进行绘制。",
- content: PolarPainterWidget()),
- FrameShower(
- title: "曲线拟合",
- author: "张风捷特烈",
- srcUrl: "/base/draw_path_fun.dart",
- info: "本样例介绍如何使用路径对函数曲线进行绘制,通过函数曲线上的少量点通过贝塞尔曲线进行拟合。",
- content: DrawPathFun()),
- FrameShower(
- title: "圆中取形",
- author: "张风捷特烈",
- srcUrl: "/base/n_side",
- info: "本样例介绍如何在圆中收集点位,绘制正多边形,是练习绘制及形成路径的很好案例。\n特殊操作:+、- 修改边数",
- content: NSidePage()),
- FrameShower(
- title: "随机对称图",
- author: "张风捷特烈",
- srcUrl: '/fun/random_portrait.dart',
- info: "本样例介绍绘制矩形及随机数处理。通过点位集合确定矩形位置信息,将其绘制出来。可以练习对数据的控制能力。\n特殊操作:点击随机生成",
- content: RandomPortrait()),
- FrameShower(
- title: "简单时钟",
- author: "张风捷特烈",
- srcUrl: '/base/clock_widget.dart',
- info: "本样例通过时钟的绘制,练习 Flutter 中旋转刻度类型的绘制技巧,并通过动画使表盘指针转动。",
- content: ClockWidget()),
- ];
- case GalleryType.anim:
- return const [
- FrameShower(
- title: "手势弹簧",
- author: "张风捷特烈",
- srcUrl: '/anim/spring_widget.dart',
- info: "本样例介绍如何绘制弹簧,通过触点竖直拖拽拉伸、压缩,放手时进行恢复动画,是一个很好的综合小案例。\n特殊操作:上下拖拽伸缩弹簧",
- content: SpringWidget()),
- FrameShower(
- title: "绕定点旋转",
- author: "张风捷特烈",
- srcUrl: '/anim/rotate_by_point',
- info: "本样例介绍如何根据以某个点为中心,进行旋转运动。以此学习两点间的角度在绘制中的应用。\n特殊操作:点击运行",
- content: RotateByPointWidget()),
- FrameShower(
- title: "流光",
- author: "张风捷特烈",
- srcUrl: '/anim/circle_halo.dart',
- info: "本样例介绍如何在绘制中使用着色器和过滤器,并通过动画进行数值变化达到旋转流光效果。",
- content: CircleHalo()),
- FrameShower(
- title: "曲线路径动画",
- author: "张风捷特烈",
- srcUrl: '/anim/draw_path.dart',
- info: "本样例介绍如何使用路径绘制函数曲线,并使用路径测量进行动画",
- content: DrawPath()),
- FrameShower(
- title: "冰墩墩线条动画",
- author: "张风捷特烈",
- srcUrl: '/anim/dundun_path.dart',
- info: "本样例会绘制 2022 年北京冬奥会吉祥物冰墩墩的路径,并使用路径测量进行动画。\n特殊操作:点击运行",
- content: DunDunPathPage()),
- FrameShower(
- title: "Bezier3 演示",
- author: "张风捷特烈",
- srcUrl: '/anim/bezier3_player',
- info: "本样例介绍如何绘制三次贝塞尔曲线,通过触点判断某点是否激活,据此控制点的位置达到拖动控制效果。\n特殊操作:单击绘点,双击清除",
- content: Bezier3Player()),
- FrameShower(
- title: "动画曲线散点图",
- author: "张风捷特烈",
- srcUrl: '/anim/curve_shower',
- info: "本样例通过直观的方式,来查看动画曲线 curve 的作用效果,让大家对动画有更深的理解。\n特殊操作:点击运行",
- content: CurveAnimShower()),
-
- ];
- case GalleryType.particle:
- return const [
- FrameShower(
- title: "随机粒子生成器",
- author: "张风捷特烈",
- srcUrl: '/particle/random',
- info: "本样例介绍如何创建随机粒子及边界反弹逻辑处理,是学习粒子运动非常好的入门案例。\n特殊操作:单击停止/运行",
- content: RandomParticle()),
- FrameShower(
- title: "粒子分裂",
- author: "张风捷特烈",
- srcUrl: '/particle/split',
- info: "本样例介绍如何对个粒子进行碰撞检测,并分裂处多个粒子,是一个比较有趣的案例。\n特殊操作:单击重置",
- content: ParticleSplit()),
- FrameShower(
- title: "图片粒子分裂",
- author: "张风捷特烈",
- srcUrl: '/particle/split_img',
- info: "本样例介绍将图片使用粒子表示,并对粒子进行动画处理,达到爆炸的效果。\n特殊操作:单击运行",
- content: SplitImage()),
- ];
- case GalleryType.fun:
- return const[
- FrameShower(
- title: "Random Portrait",
- author: "张风捷特烈",
- srcUrl: '/fun/random_portrait.dart',
- info: "本样例介绍绘制矩形及随机数处理。通过点位集合确定矩形位置信息,将其绘制出来。可以练习对数据的控制能力。\n特殊操作:点击随机生成",
- content: RandomPortrait()),
- FrameShower(
- title: "冰墩墩",
- author: "张风捷特烈",
- srcUrl: '/fun/dundun_view.dart',
- info: "本样例是绘制 2022 年北京冬奥会吉祥物冰墩墩的形体,从中可以学到路径绘制、渐变色等知识。",
- content: DunDunView()),
- FrameShower(
- title: "蒲丰投针试验",
- author: "张风捷特烈",
- srcUrl: '/fun/bufeng',
- info: "本样实现蒲丰投针试验的测试过程,根据概率来估算圆周率。其中可以学习到一些绘制小技巧已经数据的逻辑处理。",
- content: BufengPanel()),
- FrameShower(
- title: "井字棋",
- author: "张风捷特烈",
- srcUrl: '/fun/stemp',
- info: "本例通过井字棋的绘制与逻辑校验,集合了手势、绘制、动画、校验等重要的技能,是一个非常好的联系案例。\n特殊操作:双击重置",
- content: StampPaper()),
- ];
- case GalleryType.art:
- return const [
- FrameShower(
- title: "Tiled Line",
- author: "generativeartistry.com",
- srcUrl: '/art/tiled_lines.dart',
- info:
- "本样例根源来自generativeartistry.com的tiled-lines,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: TiledLines(),
- ),
- FrameShower(
- title: "Joy Division",
- author: "generativeartistry.com",
- srcUrl: '/art/joy_division.dart',
- info:
- "本样例根源来自generativeartistry.com的joy-division,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: JoyDivision(),
- ),
- FrameShower(
- title: "Cubic Disarray",
- author: "generativeartistry.com",
- srcUrl: '/art/cubic_disarray.dart',
- info:
- "本样例根源来自generativeartistry.com的cubic-disarray,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: CubicDisarray(),
- ),
- FrameShower(
- title: "Triangular Mesh",
- author: "generativeartistry.com",
- srcUrl: '/art/triangular_mesh.dart',
- info:
- "本样例根源来自generativeartistry.com的triangular-mesh,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: TriangularMesh(),
- ),
- FrameShower(
- title: "Un Deux Trois",
- srcUrl: '/art/un_deux_trois.dart',
- author: "generativeartistry.com",
- info:
- "本样例根源来自generativeartistry.com的un-deux-trois,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: UnDeuxTrois(),
- ),
- FrameShower(
- title: "Circle Packing",
- author: "generativeartistry.com",
- srcUrl: '/art/circle_packing.dart',
- info:
- "本样例根源来自generativeartistry.com的circle-packing,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: CirclePacking(),
- ),
- FrameShower(
- title: "Hypnotic Squares",
- author: "generativeartistry.com",
- srcUrl: '/art/hypnotic_squares.dart',
- info:
- "本样例根源来自generativeartistry.com的hypnotic-squares,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: HypnoticSquares(),
- ),
- FrameShower(
- title: "Piet Mondrian",
- author: "generativeartistry.com",
- srcUrl: '/art/piet_mondrian.dart',
- info:
- "本样例根源来自generativeartistry.com的piet-mondrian,由xrr2016使用Flutter实现。仓库地址:flutter-generative-artistry",
- content: PietMondrian(),
- )
- ];
- default:
- return [];
- }
- }
-}
diff --git a/lib/point_system/api/app_info.dart b/lib/point_system/api/app_info.dart
deleted file mode 100644
index b43de5e5..00000000
--- a/lib/point_system/api/app_info.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:equatable/equatable.dart';
-import 'package:utils/utils.dart';
-
-class AppInfoApi {
-
- static Future> getAppVersion({required String appName}) async {
- String errorMsg = "";
- var result = await HttpUtil.instance
- .client
- .get(PathUnit.appInfo+"/$appName")
- .catchError((err) {
- errorMsg = err.toString();
- });
-
- // 获取的数据非空且 status = true
- if (result.data != null && result.data['status']) {
- // 说明有数据
- if (result.data['data'] != null) {
- return TaskResult.success(
- data: AppInfo(
- appName: result.data['data']['appName'],
- appVersion: result.data['data']['appVersion'],
- appUrl: result.data['data']['appUrl'],
- appSize: result.data['data']['appSize'],
- ));
- } else {
- return const TaskResult.success(data: null);
- }
- }
- return TaskResult.error(msg: '请求错误: $errorMsg');
- }
-}
-
-class AppInfo extends Equatable{
- final String appName;
- final String appVersion;
- final String appUrl;
- final int appSize;
-
- const AppInfo({
- required this.appName,
- required this.appVersion,
- required this.appUrl,
- required this.appSize,
- });
-
- @override
- List get props => [appName,appVersion,appUrl,appSize];
-
- @override
- String toString() {
- return 'AppInfo{appName: $appName, appVersion: $appVersion, appUrl: $appUrl, appSize: $appSize}';
- }
-}
\ No newline at end of file
diff --git a/lib/point_system/api/category_api.dart b/lib/point_system/api/category_api.dart
deleted file mode 100644
index 888f5c3a..00000000
--- a/lib/point_system/api/category_api.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:utils/utils.dart';
-
-
-/// create by 张风捷特烈 on 2021/2/24
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class CategoryApi {
- static Future> uploadCategoryData(
- {required String data, required String likeData}) async {
- String errorMsg = "";
-
- var result = await HttpUtil.instance.client.post(
- PathUnit.categoryDataSync,
- data: {"data": data, "likeData": likeData}).catchError((err) {
- errorMsg = err.toString();
- });
-
- if (result.data != null) {
- return TaskResult.success(data:result.data);
- }
-
- return TaskResult.error(msg: '请求错误: $errorMsg');
- }
-
- static Future> getCategoryData() async {
- String errorMsg = "";
- var result = await HttpUtil.instance
- .client
- .get(PathUnit.categoryData)
- .catchError((err) {
- errorMsg =err.toString();
-
- });
-
- // 获取的数据非空且 status = true
- if (result.data != null && result.data['status']) {
- // 说明有数据
- if (result.data['data'] != null) {
- return TaskResult.success(data:CategoryData.fromJson(result.data['data']));
- } else {
- return const TaskResult.success(data:null);
- }
- }
-
- return TaskResult.error(msg: '请求错误: $errorMsg');
- }
-}
-
-class CategoryData{
- final int categoryDataId;
- final int userId;
- final String data;
- final String likeData;
-
- CategoryData(
- {required this.categoryDataId,
- required this.userId,
- required this.data,
- required this.likeData});
-
- factory CategoryData.fromJson(Map map) {
- return CategoryData(
- categoryDataId: map['categoryDataId'],
- userId: map["userId"],
- likeData: map["likeData"],
- data: map["data"]);
- }
-}
\ No newline at end of file
diff --git a/lib/point_system/api/issues_api.dart b/lib/point_system/api/issues_api.dart
deleted file mode 100644
index 6d2040df..00000000
--- a/lib/point_system/api/issues_api.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'dart:convert';
-
-import 'package:dio/dio.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-
-/// create by 张风捷特烈 on 2020/6/17
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-const kBaseUrl = 'http://119.45.173.197:8080/api/v1';
-
-class IssuesApi {
- static Dio dio = Dio(BaseOptions(baseUrl: kBaseUrl));
-
- static Future getRepoFlutterUnit() async {
- Response rep = await dio.get('/repository/name/FlutterUnit');
- dynamic repoStr = rep.data['data']['repositoryData'];
- return Repository.fromJson(json.decode(repoStr));
- }
-
- static Future> getIssues(
- {int page = 1, int pageSize = 100}) async {
- List res = (await dio.get('/point',
- queryParameters: {"page": page, "pageSize": pageSize}))
- .data['data'] as List;
- return res.map((e) => Issue.fromJson(json.decode(e['pointData']))).toList();
- }
-
- static Future> getIssuesComment(int pointId) async {
- List res = (await dio.get('/pointComment/$pointId')).data['data'] as List;
- return res
- .map((e) => IssueComment.fromJson(json.decode(e['pointCommentData'])))
- .toList();
- }
-}
diff --git a/lib/point_system/blocs/point_bloc/point_bloc.dart b/lib/point_system/blocs/point_bloc/point_bloc.dart
deleted file mode 100644
index fd4d3281..00000000
--- a/lib/point_system/blocs/point_bloc/point_bloc.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/point_system/api/issues_api.dart';
-
-import 'point_event.dart';
-import 'point_state.dart';
-
-
-/// create by 张风捷特烈 on 2020-09-03
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class PointBloc extends Bloc {
- PointBloc() : super(PointLoading()){
- on(_onEventLoadPoint);
- }
-
- void _onEventLoadPoint(PointEvent event,Emitter emit) async{
- emit( PointLoading());
- try {
- final issues = await IssuesApi.getIssues();
- emit( PointLoaded(issues));
- } catch (err) {
- print(err);
- emit( PointLoadFailure(err.toString()));
- }
- }
-}
diff --git a/lib/point_system/blocs/point_bloc/point_event.dart b/lib/point_system/blocs/point_bloc/point_event.dart
deleted file mode 100644
index 5c686d59..00000000
--- a/lib/point_system/blocs/point_bloc/point_event.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-import 'package:equatable/equatable.dart';
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-abstract class PointEvent extends Equatable {
-
-}
-
-class EventLoadPoint extends PointEvent{
-
- @override
- List get props => [];
-
-}
\ No newline at end of file
diff --git a/lib/point_system/blocs/point_bloc/point_state.dart b/lib/point_system/blocs/point_bloc/point_state.dart
deleted file mode 100644
index 43b8dc9e..00000000
--- a/lib/point_system/blocs/point_bloc/point_state.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:equatable/equatable.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-abstract class PointState extends Equatable{
-
-}
-
-class PointLoading extends PointState{
- @override
- List get props => [];
-}
-
-class PointLoaded extends PointState{
-
- final List issues;
-
- PointLoaded(this.issues);
-
- @override
- List get props => [issues];
-}
-
-
-class PointLoadFailure extends PointState{
-
- final String error;
-
- PointLoadFailure(this.error);
-
- @override
- List get props => [error];
-}
\ No newline at end of file
diff --git a/lib/point_system/blocs/point_comment_bloc/point_comment_bloc.dart b/lib/point_system/blocs/point_comment_bloc/point_comment_bloc.dart
deleted file mode 100644
index 4977bf68..00000000
--- a/lib/point_system/blocs/point_comment_bloc/point_comment_bloc.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/point_system/api/issues_api.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-
-
-import 'point_comment_event.dart';
-import 'point_comment_state.dart';
-
-
-/// create by 张风捷特烈 on 2020-09-03
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class PointCommentBloc extends Bloc {
-
- PointCommentBloc() : super(PointCommentInitial()){
- on(_onEventLoadPointComment);
- }
-
- void _onEventLoadPointComment(EventLoadPointComment event,Emitter emit) async{
- emit( PointCommentLoading(event.point));
- if(event.point.number==null){
- emit( PointCommentLoadFailure('point_bloc id 为空'));
- }
- try {
- final List comments = await IssuesApi.getIssuesComment(event.point.number!);
- comments.sort((a,b)=>a.createdAt!.compareTo(b.createdAt!));
- emit( PointCommentLoaded(event.point,comments));
- } catch (err) {
- print(err);
- emit( PointCommentLoadFailure(err.toString()));
- }
- }
-}
diff --git a/lib/point_system/blocs/point_comment_bloc/point_comment_event.dart b/lib/point_system/blocs/point_comment_bloc/point_comment_event.dart
deleted file mode 100644
index 15da9ed5..00000000
--- a/lib/point_system/blocs/point_comment_bloc/point_comment_event.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-import 'package:equatable/equatable.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-abstract class PointCommentEvent extends Equatable {}
-
-class EventLoadPointComment extends PointCommentEvent {
- final Issue point;
-
- EventLoadPointComment(this.point);
-
- @override
- List get props => [point];
-}
diff --git a/lib/point_system/blocs/point_comment_bloc/point_comment_state.dart b/lib/point_system/blocs/point_comment_bloc/point_comment_state.dart
deleted file mode 100644
index 1b53df4e..00000000
--- a/lib/point_system/blocs/point_comment_bloc/point_comment_state.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-import 'package:equatable/equatable.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-abstract class PointCommentState extends Equatable{
-
-}
-
-class PointCommentInitial extends PointCommentState{
-
-
- @override
- List get props => [];
-}
-
-class PointCommentLoading extends PointCommentState{
- final Issue issue;
-
- PointCommentLoading(this.issue);
-
- @override
- List get props => [issue];
-}
-
-class PointCommentLoaded extends PointCommentState{
-
- final Issue issue;
- final List comments;
-
- PointCommentLoaded(this.issue,this.comments);
-
- @override
- List get props => [issue,comments];
-
- @override
- String toString() {
- return 'PointCommentLoaded{issue: $issue, comments: $comments}';
- }
-}
-
-
-class PointCommentLoadFailure extends PointCommentState{
-
- final String error;
-
- PointCommentLoadFailure(this.error);
-
- @override
- List get props => [error];
-}
\ No newline at end of file
diff --git a/lib/point_system/blocs/point_system_bloc.dart b/lib/point_system/blocs/point_system_bloc.dart
deleted file mode 100644
index e9642c71..00000000
--- a/lib/point_system/blocs/point_system_bloc.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-export './point_comment_bloc/point_comment_bloc.dart';
-export './point_comment_bloc/point_comment_event.dart';
-export './point_comment_bloc/point_comment_state.dart';
-
-export './point_bloc/point_bloc.dart';
-export './point_bloc/point_event.dart';
-export './point_bloc/point_state.dart';
-
-
diff --git a/lib/point_system/views/desk_ui/desk_point_page.dart b/lib/point_system/views/desk_ui/desk_point_page.dart
deleted file mode 100644
index 904495ea..00000000
--- a/lib/point_system/views/desk_ui/desk_point_page.dart
+++ /dev/null
@@ -1,141 +0,0 @@
-import 'package:flutter/gestures.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-import 'package:url_launcher/url_launcher.dart';
-
-import '../../../app/plateform_adapter/window/windows_adapter.dart';
-import '../../../widget_ui/desk_ui/widget_panel/window_buttons.dart';
-import '../../blocs/point_bloc/point_bloc.dart';
-import '../../blocs/point_bloc/point_event.dart';
-import '../../github_model/repository.dart';
-import '../../views/issues_point/issues_point_page.dart';
-import 'github_repo_panel.dart';
-
-class DeskPointPage extends StatefulWidget {
- const DeskPointPage({Key? key}) : super(key: key);
-
- @override
- State createState() => _DeskPointPageState();
-}
-
-class _DeskPointPageState extends State {
-
- final Repository _repository = Repository.fromJson({
- 'full_name': 'toly1994328/FlutterUnit',
- 'license': {"spdx_id": 'GPL-3.0'},
- 'description':
- '【Flutter 集录指南 App】The unity of flutter, The unity of coder.',
- 'stargazers_count': 5840,
- 'forks_count': 956,
- 'subscribers_count': 126,
- 'open_issues_count': 40,
- });
-
- @override
- Widget build(BuildContext context) {
- return BlocProvider(
- create: (_) => PointBloc()..add(EventLoadPoint()),
- child: Scaffold(
- body: Column(
- children: [
- SimpleDeskTopBar(
- leading: Text(
- 'Flutter 要点集录',
- style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
- ),
- ),
- Divider(height: 1),
- Expanded(
- child: Row(
- children: [
- Column(
- children: [
- GithubRepoPanel(
- repository: _repository,
- ),
- Expanded(
- child: SizedBox(
- width: 250,
- child: IssuesTip())
- )
- ],
- ),
- VerticalDivider(width: 1,),
- Expanded(flex: 2, child: IssuesPointContent()),
- ],
- ))
- ],
- ),
- ),
- );
- }
-}
-
-class IssuesTip extends StatelessWidget {
- const IssuesTip({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Padding(
- padding: const EdgeInsets.all(8.0),
- child: Text.rich(
- TextSpan(children: [
- TextSpan(
- text: '* 注: ',
- style: TextStyle(
- color: Colors.red,
- fontWeight: FontWeight.bold)),
- TextSpan(
- text:
- '要点集录中的 QA 数据收录在 FlutterUnit 以 point 为标签的 issues 中。如果需要提供数据,在 issues 中问答即可。'),
- TextSpan(
- text: '点击这里跳转',
- mouseCursor: SystemMouseCursors.click,
- recognizer: TapGestureRecognizer()
- ..onTap = _toUrl,
- style: TextStyle(
- color: Colors.blue,
- decoration: TextDecoration.underline,
- fontWeight: FontWeight.bold)),
- ]),
- style: TextStyle(fontSize: 14),
- ),
- );
- }
-
- void _toUrl() async{
- String url = 'https://github.com/toly1994328/FlutterUnit/issues?q=label%3Apoint+';
- if (!await launchUrl(Uri.parse(url))) {
- throw Exception('Could not launch $url');
- }
- }
-}
-
-
-class SimpleDeskTopBar extends StatelessWidget {
- final Widget? leading;
-
- const SimpleDeskTopBar({super.key, this.leading});
-
- @override
- Widget build(BuildContext context) {
- return DragToMoveAreaNoDouble(
- child: Container(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- height: 64,
- color: Colors.white,
- child: Row(
- children: [
- if (leading != null) leading!,
- const Spacer(),
- const SizedBox(
- width: 20,
- ),
- const WindowButtons(),
- ],
- ),
- ),
- );
- }
-}
diff --git a/lib/point_system/views/issues_point/issue_item.dart b/lib/point_system/views/issues_point/issue_item.dart
deleted file mode 100644
index 0cb8f276..00000000
--- a/lib/point_system/views/issues_point/issue_item.dart
+++ /dev/null
@@ -1,93 +0,0 @@
-import 'dart:ui';
-
-import 'package:app_config/app_config.dart';
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_unit/app/utils/convert_man.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class IssueItem extends StatelessWidget {
- final Issue issue;
-
- const IssueItem({Key? key, required this.issue}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
- decoration: BoxDecoration(
- border: Border(
- bottom: BorderSide(
- color: Theme.of(context).dividerColor,
- width: 1 / window.devicePixelRatio))),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- _buildTop(),
- Padding(
- padding: const EdgeInsets.only(top: 5.0, bottom: 5.0, left: 10),
- child: Text(
- '${issue.title}',
- style: const TextStyle(fontSize: 15, color: Colors.grey, shadows: [
- Shadow(color: Colors.white, offset: Offset(1, .5))
- ]),
- ),
- ),
- Row(
- children: [
- const Spacer(),
- WrapColor(
- color: Colors.greenAccent,
- child: Text(
- issue.commentNum.toString(),
- style: const TextStyle(color: Colors.white),
- )),
- const SizedBox(
- width: 5,
- ),
- const Icon(
- TolyIcon.icon_common,
- size: 20,
- ),
- ],
- )
- ],
- ),
- );
- }
-
- Widget _buildTop() {
- return Row(
- children: [
- CircleImage(
- image: NetworkImage(issue.user?.avatarUrl??''),
- size: 40,
- borderSize: 2,
- ),
- const SizedBox(
- width: 10,
- ),
- WrapColor(
- child: Text(
- "#${issue.number}",
- style: const TextStyle(color: Colors.white),
- )),
- const SizedBox(
- width: 10,
- ),
- Text(
- '${issue.user?.login}',
- style: const TextStyle(fontWeight: FontWeight.bold),
- ),
- const Spacer(),
- Text(ConvertMan.time2string(issue.createdAt!)),
- ],
- );
- }
-}
\ No newline at end of file
diff --git a/lib/point_system/views/issues_point/issues_detail.dart b/lib/point_system/views/issues_point/issues_detail.dart
deleted file mode 100644
index ef5c78ff..00000000
--- a/lib/point_system/views/issues_point/issues_detail.dart
+++ /dev/null
@@ -1,181 +0,0 @@
-import 'package:components/toly_ui/toly_ui.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_unit/app/utils/convert_man.dart';
-import 'package:flutter_unit/point_system/blocs/point_system_bloc.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-/// create by 张风捷特烈 on 2020/9/3
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class IssuesDetailPage extends StatelessWidget {
- const IssuesDetailPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: const Text('Flutter Point'),
- ),
- body: BlocBuilder(
- builder: _buildContent),
- );
- }
-
- Widget _buildContent(BuildContext context, PointCommentState state) {
- if (state is PointCommentLoading) {
- return IssueTitle(issue: state.issue);
- }
-
- if (state is PointCommentLoaded) {
- return CustomScrollView(
- slivers: [
- SliverToBoxAdapter(child: IssueTitle(issue: state.issue)),
- SliverList(
- delegate: SliverChildBuilderDelegate(
- (ctx, int index) => IssueCommentWidget(
- comment: state.comments[index],
- ),
- childCount: state.comments.length),
- )
- ],
- );
- }
-
- return Container();
- }
-}
-
-class IssueTitle extends StatelessWidget {
- final Issue issue;
-
- const IssueTitle({Key? key, required this.issue}) : super(key: key);
-
- String get issueDesHtml => issue.bodyHtml != null
- ? issue.bodyHtml!
- : (issue.body != null)
- ? issue.body!
- : "";
-
- @override
- Widget build(BuildContext context) {
- return SingleChildScrollView(
- child: Column(
- children: [
- Stack(
- children: [
- Container(
- padding: const EdgeInsets.symmetric(horizontal: 8),
- child: Panel(
- child: Text(
- '${issue.title}',
- style: const TextStyle(
- fontSize: 18, fontWeight: FontWeight.bold),
- )),
- ),
- Positioned(
- right: 10,
- bottom: 10,
- child: WrapColor(
- child: Text(
- '#${issue.number}',
- style: const TextStyle(color: Colors.white),
- ),
- )),
- ],
- ),
- const Divider(),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 8.0),
- child: WrapColor(
- color: Colors.blue.withAlpha(22),
- child: ListTile(
- dense: true,
- leading: CircleImage(
- size: 40,
- borderSize: 1,
- image: NetworkImage(issue.user!.avatarUrl!),
- ),
- title: Text(issue.user!.login!),
- subtitle: Row(
- children: [
- Text('创建于:${ConvertMan.time2string(issue.createdAt!)}'),
- const Spacer(),
- WrapColor(
- color: Colors.green,
- child: Text(
- '更新于:${ConvertMan.time2string(issue.updatedAt!)}',
- style: const TextStyle(color: Colors.white),
- )),
- ],
- ),
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: MarkdownWidget(
- markdownData: issueDesHtml, style: MarkdownWidget.kWhite),
- ),
- const Divider(
- thickness: 2,
- )
- ],
- ),
- );
- }
-}
-
-class IssueCommentWidget extends StatelessWidget {
- final IssueComment comment;
-
- const IssueCommentWidget({Key? key, required this.comment}) : super(key: key);
-
- String get issueDesHtml => comment.bodyHtml != null
- ? comment.bodyHtml!
- : (comment.body != null)
- ? comment.body!
- : "";
-
- @override
- Widget build(BuildContext context) {
- return Column(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 8.0),
- child: WrapColor(
- color: Colors.blue.withAlpha(22),
- child: ListTile(
- dense: true,
- leading: CircleImage(
- size: 40,
- borderSize: 1,
- image: NetworkImage(comment.user!.avatarUrl!),
- ),
- title: Text(comment.user!.login!),
- subtitle: Row(
- children: [
- Text('创建于:${ConvertMan.time2string(comment.createdAt!)}'),
- const Spacer(),
- WrapColor(
- color: Colors.green,
- child: Text(
- '更新于:${ConvertMan.time2string(comment.updatedAt!)}',
- style: const TextStyle(color: Colors.white),
- )),
- ],
- ),
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: MarkdownWidget(
- markdownData: issueDesHtml, style: MarkdownWidget.kWhite),
- ),
- const Divider(thickness: 2)
- ],
- );
- }
-}
diff --git a/lib/point_system/views/issues_point/issues_point_page.dart b/lib/point_system/views/issues_point/issues_point_page.dart
deleted file mode 100644
index 0cd07104..00000000
--- a/lib/point_system/views/issues_point/issues_point_page.dart
+++ /dev/null
@@ -1,164 +0,0 @@
-import 'package:app_config/app_config.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_spinkit/flutter_spinkit.dart';
-
-import 'package:flutter_unit/app/router/unit_router.dart';
-import 'package:flutter_unit/point_system/api/issues_api.dart';
-import 'package:flutter_unit/point_system/blocs/point_system_bloc.dart';
-import 'package:flutter_unit/point_system/github_model/github_model.dart';
-
-import 'issue_item.dart';
-import 'issues_detail.dart';
-import 'repo_widget.dart';
-
-/// create by 张风捷特烈 on 2020/6/17
-/// contact me by email 1981462002@qq.com
-/// 说明:
-
-class IssuesPointScope extends StatelessWidget {
- const IssuesPointScope({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return MultiBlocProvider(providers: [
- BlocProvider(create: (_) => PointBloc()..add(EventLoadPoint())),
- ], child: const IssuesPointPage(),
- );
- }
-}
-
-class IssuesPointPage extends StatelessWidget {
- const IssuesPointPage({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return const Scaffold(body: IssuesPointContent());
- }
-}
-
-class IssuesPointContent extends StatefulWidget {
- const IssuesPointContent({Key? key}) : super(key: key);
-
- @override
- _IssuesPointContentState createState() => _IssuesPointContentState();
-}
-
-class _IssuesPointContentState extends State {
- Repository? _repository;
-
- @override
- void initState() {
- super.initState();
- _loadRepo();
- }
-
- @override
- Widget build(BuildContext context) {
- return BlocBuilder(
- builder: (_, state) => RefreshIndicator(
- onRefresh: _loadIssues,
- child: CustomScrollView(slivers: [
- // _buildSliverAppBar(),
- buildContentByState(state)
- ]),
- ));
- }
-
- Widget buildContentByState(PointState state) {
- if (state is PointLoading) {
- return const SliverPadding(
- padding: EdgeInsets.only(top: 150),
- sliver: SliverToBoxAdapter(
- child: Center(
- child: SpinKitCircle(
- color: Colors.blue,
- ),
- )),
- );
- }
-
- if (state is PointLoaded) {
- List issues = state.issues;
- return SliverList(
- delegate: SliverChildBuilderDelegate(
- (ctx, int index) => GestureDetector(
- onTap: () {
- Navigator.of(context).push(Right2LeftRouter(
- child: BlocProvider(
- create: (_) => PointCommentBloc()
- ..add(EventLoadPointComment(issues[index])),
- child: const IssuesDetailPage())));
-
- // Navigator.pushNamed(ctx, UnitRouter.
- // );
- },
- child: IssueItem(issue: issues[index])),
- childCount: issues.length),);
- }
-
- if (state is PointLoadFailure) {
- return SliverPadding(
- padding: const EdgeInsets.only(top: 40),
- sliver: SliverToBoxAdapter(
- child: Center(
- child: Text(state.error),
- )),
- );
- }
-
- return const SliverPadding(
- padding: EdgeInsets.zero,
- );
- }
-
- Widget _buildSliverAppBar() {
- return SliverAppBar(
- expandedHeight: 210.0,
-// leading: _buildLeading(),
- title: const Text('Flutter要点集录'),
-// actions: _buildActions(),
- elevation: 5,
- pinned: true,
- actions: [
- IconButton(
- icon: const Icon(
- Icons.help_outline,
- color: Colors.white,
- ),
- onPressed: () {
- Navigator.of(context).pushNamed(UnitRouter.bug);
- })
- ],
- backgroundColor: Colors.blue,
- flexibleSpace: FlexibleSpaceBar(
- //伸展处布局
- titlePadding: const EdgeInsets.only(left: 55, bottom: 15), //标题边距
- collapseMode: CollapseMode.parallax, //视差效果
- background: _repository == null
- ? const Center(
- child: SpinKitFadingCube(
- color: Colors.white,
- ),
- )
- : RepoWidget(
- repository: _repository!,
- ),
- ),
- );
- }
-
- Future _loadIssues() async {
- BlocProvider.of(context).add(EventLoadPoint());
- await Future.delayed(const Duration(milliseconds: 200));
- }
-
- void _loadRepo() async {
- final Repository? result = await IssuesApi.getRepoFlutterUnit();
- setState(() {
- if (result != null) {
- _repository = result;
- }
- });
- }
-}
diff --git a/lib/src/flutter_unit.dart b/lib/src/flutter_unit.dart
new file mode 100644
index 00000000..0f3b0ee7
--- /dev/null
+++ b/lib/src/flutter_unit.dart
@@ -0,0 +1,91 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+
+import 'package:go_router/go_router.dart';
+import 'package:l10n/gen_l10n/app_localizations.dart';
+import 'package:l10n/l10n.dart';
+import 'package:tolyui/app/toly_ui.dart';
+import 'package:widget_module/widget_module.dart';
+import 'package:widget_module/blocs/blocs.dart';
+import 'package:note/note.dart';
+import 'l10n/gen/app_l10n.dart';
+import 'l10n/locale_provider.dart';
+import 'navigation/router/app_route.dart';
+
+/// create by 张风捷特烈 on 2020/4/28
+/// contact me by email 1981462002@qq.com
+/// 说明: 应用主程序
+
+class FlutterUnit3 extends StatefulWidget {
+ const FlutterUnit3({super.key});
+
+ @override
+ State createState() => _FlutterUnit3State();
+}
+
+class _FlutterUnit3State extends State with LocalProvider {
+ final GoRouter _router = GoRouter(
+ initialLocation: AppRoute.splash.url,
+ routes: [appRoute],
+ onException: (BuildContext ctx, GoRouterState state, GoRouter router) {
+ router.go(AppRoute.globalError.url, extra: state.uri.toString());
+ },
+ );
+
+ @override
+ void initState() {
+ super.initState();
+ _initWeb();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ AppConfig state = context.watch().state;
+ ThemeData dark = darkTheme(state);
+ ThemeData light = lightTheme(state);
+ return BlocListener(
+ listenWhen: (p, n) => p.language != n.language,
+ listener: _onLocaleChange,
+ child: DefaultTextStyle(
+ style: TextStyle(fontFamily: state.fontFamily),
+ child: TolyUiApp.router(
+ routerConfig: _router,
+ showPerformanceOverlay: state.showPerformanceOverlay,
+ title: StrUnit.appName,
+ debugShowCheckedModeBanner: false,
+ localizationsDelegates: localizationsDelegates,
+ supportedLocales: supportedLocales,
+ locale: state.language.locale,
+ themeMode: state.themeMode,
+ darkTheme: dark,
+ theme: light,
+ ),
+ ),
+ );
+ }
+
+ void _initWeb() {
+ if (!kAppEnv.isWeb) return;
+ GoRouter.optionURLReflectsImperativeAPIs = true;
+ context.initWidgetData();
+ }
+
+ void _onLocaleChange(BuildContext context, AppConfig state) {
+ context.read().changeLocale(state.language.locale);
+ }
+
+ @override
+ Iterable? get localizationsDelegates => const [
+ AppL10n.delegate,
+ AppLocalizations.delegate,
+ GlobalMaterialLocalizations.delegate,
+ GlobalCupertinoLocalizations.delegate,
+ GlobalWidgetsLocalizations.delegate,
+ FlutterQuillLocalizations.delegate,
+ ];
+
+ @override
+ List get supportedLocales => l10nLocales;
+}
diff --git a/lib/src/l10n/arb/app_de.arb b/lib/src/l10n/arb/app_de.arb
new file mode 100644
index 00000000..915213a3
--- /dev/null
+++ b/lib/src/l10n/arb/app_de.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Widget-Sammlung",
+ "deskTabPainter": "Zeichnungssammlung",
+ "deskTabKnowledge": "Wissensdatenbank",
+ "deskTabTools": "Werkzeugkasten",
+ "deskTabMine": "App-Info",
+ "messageBoard": "Pinnwand",
+ "mobileTabWidgets": "Widgets",
+ "mobileTabPainter": "Malen",
+ "mobileTabKnowledge": "Wissen",
+ "mobileTabTools": "Werkzeuge",
+ "mobileTabMine": "Mein",
+ "newBoard": "Neu",
+ "news": "Neuigkeiten",
+ "moreNews": "Mehr News"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_en.arb b/lib/src/l10n/arb/app_en.arb
new file mode 100644
index 00000000..9a3d0f4f
--- /dev/null
+++ b/lib/src/l10n/arb/app_en.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Widgets",
+ "deskTabPainter": "Painter",
+ "deskTabKnowledge": "Knowledge",
+ "deskTabTools": "Treasure",
+ "deskTabMine": "About",
+ "messageBoard": "Message Board",
+ "mobileTabWidgets": "Widgets",
+ "mobileTabPainter": "Painter",
+ "mobileTabKnowledge": "Knowledge",
+ "mobileTabTools": "Treasure",
+ "mobileTabMine": "Mine",
+ "newBoard": "New",
+ "news": "News",
+ "moreNews": "More News"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_es.arb b/lib/src/l10n/arb/app_es.arb
new file mode 100644
index 00000000..ede49fdb
--- /dev/null
+++ b/lib/src/l10n/arb/app_es.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Colección de widgets",
+ "deskTabPainter": "Colección de dibujos",
+ "deskTabKnowledge": "Centro de conocimiento",
+ "deskTabTools": "Caja de herramientas",
+ "deskTabMine": "Info App",
+ "messageBoard": "Tablero de Mensajes",
+ "mobileTabWidgets": "Widgets",
+ "mobileTabPainter": "Dibujo",
+ "mobileTabKnowledge": "Conocimiento",
+ "mobileTabTools": "Herramientas",
+ "mobileTabMine": "Mi",
+ "newBoard": "Nuevo",
+ "news": "Noticias",
+ "moreNews": "Más noticias"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_fr.arb b/lib/src/l10n/arb/app_fr.arb
new file mode 100644
index 00000000..2e271c2d
--- /dev/null
+++ b/lib/src/l10n/arb/app_fr.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Collection de widgets",
+ "deskTabPainter": "Collection de dessins",
+ "deskTabKnowledge": "Base de connaissances",
+ "deskTabTools": "Boîte à outils",
+ "deskTabMine": "Infos App",
+ "messageBoard": "Tableau de messages",
+ "mobileTabWidgets": "Widgets",
+ "mobileTabPainter": "Dessin",
+ "mobileTabKnowledge": "Connaissances",
+ "mobileTabTools": "Outils",
+ "mobileTabMine": "Moi",
+ "newBoard": "Nouveau",
+ "news": "Actualités",
+ "moreNews": "Plus d'actualités"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_it.arb b/lib/src/l10n/arb/app_it.arb
new file mode 100644
index 00000000..7cf9050c
--- /dev/null
+++ b/lib/src/l10n/arb/app_it.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Raccolta widget",
+ "deskTabPainter": "Raccolta disegni",
+ "deskTabKnowledge": "Hub conoscitivo",
+ "deskTabTools": "Cassetta degli attrezzi",
+ "deskTabMine": "Info App",
+ "messageBoard": "Bacheca",
+ "mobileTabWidgets": "Widget",
+ "mobileTabPainter": "Disegno",
+ "mobileTabKnowledge": "Conoscenza",
+ "mobileTabTools": "Strumenti",
+ "mobileTabMine": "Io",
+ "newBoard": "Nuovo",
+ "news": "Notizie",
+ "moreNews": "Altre notizie"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_ja.arb b/lib/src/l10n/arb/app_ja.arb
new file mode 100644
index 00000000..dcf1cb0c
--- /dev/null
+++ b/lib/src/l10n/arb/app_ja.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "ウィジェット集",
+ "deskTabPainter": "描画集",
+ "deskTabKnowledge": "ナレッジハブ",
+ "deskTabTools": "ツールボックス",
+ "deskTabMine": "アプリ情報",
+ "messageBoard": "掲示板",
+ "mobileTabWidgets": "ウィジェット",
+ "mobileTabPainter": "描画",
+ "mobileTabKnowledge": "知識",
+ "mobileTabTools": "ツール",
+ "mobileTabMine": "マイ",
+ "newBoard": "新規作成",
+ "news": "最新情報",
+ "moreNews": "もっと見る"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_ko.arb b/lib/src/l10n/arb/app_ko.arb
new file mode 100644
index 00000000..a3952eb9
--- /dev/null
+++ b/lib/src/l10n/arb/app_ko.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "위젯 모음집",
+ "deskTabPainter": "그림 모음집",
+ "deskTabKnowledge": "지식 허브",
+ "deskTabTools": "도구 상자",
+ "deskTabMine": "앱 정보",
+ "messageBoard": "게시판",
+ "mobileTabWidgets": "위젯",
+ "mobileTabPainter": "그리기",
+ "mobileTabKnowledge": "지식",
+ "mobileTabTools": "도구",
+ "mobileTabMine": "내 정보",
+ "newBoard": "새 글",
+ "news": "최신 소식",
+ "moreNews": "더 보기"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_pt.arb b/lib/src/l10n/arb/app_pt.arb
new file mode 100644
index 00000000..4b877bfa
--- /dev/null
+++ b/lib/src/l10n/arb/app_pt.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Coleção de widgets",
+ "deskTabPainter": "Coleção de desenhos",
+ "deskTabKnowledge": "Hub de conhecimento",
+ "deskTabTools": "Caixa de ferramentas",
+ "deskTabMine": "Info App",
+ "messageBoard": "Quadro de Mensagens",
+ "mobileTabWidgets": "Widgets",
+ "mobileTabPainter": "Desenho",
+ "mobileTabKnowledge": "Conhecimento",
+ "mobileTabTools": "Ferramentas",
+ "mobileTabMine": "Meu",
+ "newBoard": "Novo",
+ "news": "Novidades",
+ "moreNews": "Mais novidades"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_ru.arb b/lib/src/l10n/arb/app_ru.arb
new file mode 100644
index 00000000..64b61c2e
--- /dev/null
+++ b/lib/src/l10n/arb/app_ru.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "Коллекция виджетов",
+ "deskTabPainter": "Коллекция рисунков",
+ "deskTabKnowledge": "База знаний",
+ "deskTabTools": "Инструменты",
+ "deskTabMine": "Информация",
+ "messageBoard": "Доска сообщений",
+ "mobileTabWidgets": "Виджеты",
+ "mobileTabPainter": "Рисование",
+ "mobileTabKnowledge": "Знания",
+ "mobileTabTools": "Инструменты",
+ "mobileTabMine": "Мои",
+ "newBoard": "Создать",
+ "news": "Новости",
+ "moreNews": "Больше новостей"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/arb/app_zh.arb b/lib/src/l10n/arb/app_zh.arb
new file mode 100644
index 00000000..5b4d2f39
--- /dev/null
+++ b/lib/src/l10n/arb/app_zh.arb
@@ -0,0 +1,16 @@
+{
+ "deskTabWidgets": "组件集录",
+ "deskTabPainter": "绘制集录",
+ "deskTabKnowledge": "知识集锦",
+ "deskTabTools": "工具宝箱",
+ "deskTabMine": "应用信息",
+ "messageBoard": "留言板",
+ "mobileTabWidgets": "组件",
+ "mobileTabPainter": "绘制",
+ "mobileTabKnowledge": "知识",
+ "mobileTabTools": "工具",
+ "mobileTabMine": "我的",
+ "newBoard": "新建 ",
+ "news": "最新资讯",
+ "moreNews": "查看更多"
+}
\ No newline at end of file
diff --git a/lib/src/l10n/gen/app_l10n.dart b/lib/src/l10n/gen/app_l10n.dart
new file mode 100644
index 00000000..39cd6ac3
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n.dart
@@ -0,0 +1,257 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:intl/intl.dart' as intl;
+
+import 'app_l10n_de.dart';
+import 'app_l10n_en.dart';
+import 'app_l10n_es.dart';
+import 'app_l10n_fr.dart';
+import 'app_l10n_it.dart';
+import 'app_l10n_ja.dart';
+import 'app_l10n_ko.dart';
+import 'app_l10n_pt.dart';
+import 'app_l10n_ru.dart';
+import 'app_l10n_zh.dart';
+
+// ignore_for_file: type=lint
+
+/// Callers can lookup localized strings with an instance of AppL10n
+/// returned by `AppL10n.of(context)`.
+///
+/// Applications need to include `AppL10n.delegate()` in their app's
+/// `localizationDelegates` list, and the locales they support in the app's
+/// `supportedLocales` list. For example:
+///
+/// ```dart
+/// import 'gen/app_l10n.dart';
+///
+/// return MaterialApp(
+/// localizationsDelegates: AppL10n.localizationsDelegates,
+/// supportedLocales: AppL10n.supportedLocales,
+/// home: MyApplicationHome(),
+/// );
+/// ```
+///
+/// ## Update pubspec.yaml
+///
+/// Please make sure to update your pubspec.yaml to include the following
+/// packages:
+///
+/// ```yaml
+/// dependencies:
+/// # Internationalization support.
+/// flutter_localizations:
+/// sdk: flutter
+/// intl: any # Use the pinned version from flutter_localizations
+///
+/// # Rest of dependencies
+/// ```
+///
+/// ## iOS Applications
+///
+/// iOS applications define key application metadata, including supported
+/// locales, in an Info.plist file that is built into the application bundle.
+/// To configure the locales supported by your app, you’ll need to edit this
+/// file.
+///
+/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
+/// Then, in the Project Navigator, open the Info.plist file under the Runner
+/// project’s Runner folder.
+///
+/// Next, select the Information Property List item, select Add Item from the
+/// Editor menu, then select Localizations from the pop-up menu.
+///
+/// Select and expand the newly-created Localizations item then, for each
+/// locale your application supports, add a new item and select the locale
+/// you wish to add from the pop-up menu in the Value field. This list should
+/// be consistent with the languages listed in the AppL10n.supportedLocales
+/// property.
+abstract class AppL10n {
+ AppL10n(String locale)
+ : localeName = intl.Intl.canonicalizedLocale(locale.toString());
+
+ final String localeName;
+
+ static AppL10n of(BuildContext context) {
+ return Localizations.of(context, AppL10n)!;
+ }
+
+ static const LocalizationsDelegate delegate = _AppL10nDelegate();
+
+ /// A list of this localizations delegate along with the default localizations
+ /// delegates.
+ ///
+ /// Returns a list of localizations delegates containing this delegate along with
+ /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
+ /// and GlobalWidgetsLocalizations.delegate.
+ ///
+ /// Additional delegates can be added by appending to this list in
+ /// MaterialApp. This list does not have to be used at all if a custom list
+ /// of delegates is preferred or required.
+ static const List> localizationsDelegates =
+ >[
+ delegate,
+ GlobalMaterialLocalizations.delegate,
+ GlobalCupertinoLocalizations.delegate,
+ GlobalWidgetsLocalizations.delegate,
+ ];
+
+ /// A list of this localizations delegate's supported locales.
+ static const List supportedLocales = [
+ Locale('de'),
+ Locale('en'),
+ Locale('es'),
+ Locale('fr'),
+ Locale('it'),
+ Locale('ja'),
+ Locale('ko'),
+ Locale('pt'),
+ Locale('ru'),
+ Locale('zh')
+ ];
+
+ /// No description provided for @deskTabWidgets.
+ ///
+ /// In zh, this message translates to:
+ /// **'组件集录'**
+ String get deskTabWidgets;
+
+ /// No description provided for @deskTabPainter.
+ ///
+ /// In zh, this message translates to:
+ /// **'绘制集录'**
+ String get deskTabPainter;
+
+ /// No description provided for @deskTabKnowledge.
+ ///
+ /// In zh, this message translates to:
+ /// **'知识集锦'**
+ String get deskTabKnowledge;
+
+ /// No description provided for @deskTabTools.
+ ///
+ /// In zh, this message translates to:
+ /// **'工具宝箱'**
+ String get deskTabTools;
+
+ /// No description provided for @deskTabMine.
+ ///
+ /// In zh, this message translates to:
+ /// **'应用信息'**
+ String get deskTabMine;
+
+ /// No description provided for @messageBoard.
+ ///
+ /// In zh, this message translates to:
+ /// **'留言板'**
+ String get messageBoard;
+
+ /// No description provided for @mobileTabWidgets.
+ ///
+ /// In zh, this message translates to:
+ /// **'组件'**
+ String get mobileTabWidgets;
+
+ /// No description provided for @mobileTabPainter.
+ ///
+ /// In zh, this message translates to:
+ /// **'绘制'**
+ String get mobileTabPainter;
+
+ /// No description provided for @mobileTabKnowledge.
+ ///
+ /// In zh, this message translates to:
+ /// **'知识'**
+ String get mobileTabKnowledge;
+
+ /// No description provided for @mobileTabTools.
+ ///
+ /// In zh, this message translates to:
+ /// **'工具'**
+ String get mobileTabTools;
+
+ /// No description provided for @mobileTabMine.
+ ///
+ /// In zh, this message translates to:
+ /// **'我的'**
+ String get mobileTabMine;
+
+ /// No description provided for @newBoard.
+ ///
+ /// In zh, this message translates to:
+ /// **'新建 '**
+ String get newBoard;
+
+ /// No description provided for @news.
+ ///
+ /// In zh, this message translates to:
+ /// **'最新资讯'**
+ String get news;
+
+ /// No description provided for @moreNews.
+ ///
+ /// In zh, this message translates to:
+ /// **'查看更多'**
+ String get moreNews;
+}
+
+class _AppL10nDelegate extends LocalizationsDelegate {
+ const _AppL10nDelegate();
+
+ @override
+ Future load(Locale locale) {
+ return SynchronousFuture(lookupAppL10n(locale));
+ }
+
+ @override
+ bool isSupported(Locale locale) => [
+ 'de',
+ 'en',
+ 'es',
+ 'fr',
+ 'it',
+ 'ja',
+ 'ko',
+ 'pt',
+ 'ru',
+ 'zh'
+ ].contains(locale.languageCode);
+
+ @override
+ bool shouldReload(_AppL10nDelegate old) => false;
+}
+
+AppL10n lookupAppL10n(Locale locale) {
+ // Lookup logic when only language code is specified.
+ switch (locale.languageCode) {
+ case 'de':
+ return AppL10nDe();
+ case 'en':
+ return AppL10nEn();
+ case 'es':
+ return AppL10nEs();
+ case 'fr':
+ return AppL10nFr();
+ case 'it':
+ return AppL10nIt();
+ case 'ja':
+ return AppL10nJa();
+ case 'ko':
+ return AppL10nKo();
+ case 'pt':
+ return AppL10nPt();
+ case 'ru':
+ return AppL10nRu();
+ case 'zh':
+ return AppL10nZh();
+ }
+
+ throw FlutterError(
+ 'AppL10n.delegate failed to load unsupported locale "$locale". This is likely '
+ 'an issue with the localizations generation tool. Please file an issue '
+ 'on GitHub with a reproducible sample app and the gen-l10n configuration '
+ 'that was used.');
+}
diff --git a/lib/src/l10n/gen/app_l10n_de.dart b/lib/src/l10n/gen/app_l10n_de.dart
new file mode 100644
index 00000000..f8e2660c
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_de.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for German (`de`).
+class AppL10nDe extends AppL10n {
+ AppL10nDe([String locale = 'de']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Widget-Sammlung';
+
+ @override
+ String get deskTabPainter => 'Zeichnungssammlung';
+
+ @override
+ String get deskTabKnowledge => 'Wissensdatenbank';
+
+ @override
+ String get deskTabTools => 'Werkzeugkasten';
+
+ @override
+ String get deskTabMine => 'App-Info';
+
+ @override
+ String get messageBoard => 'Pinnwand';
+
+ @override
+ String get mobileTabWidgets => 'Widgets';
+
+ @override
+ String get mobileTabPainter => 'Malen';
+
+ @override
+ String get mobileTabKnowledge => 'Wissen';
+
+ @override
+ String get mobileTabTools => 'Werkzeuge';
+
+ @override
+ String get mobileTabMine => 'Mein';
+
+ @override
+ String get newBoard => 'Neu';
+
+ @override
+ String get news => 'Neuigkeiten';
+
+ @override
+ String get moreNews => 'Mehr News';
+}
diff --git a/lib/src/l10n/gen/app_l10n_en.dart b/lib/src/l10n/gen/app_l10n_en.dart
new file mode 100644
index 00000000..65194446
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_en.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for English (`en`).
+class AppL10nEn extends AppL10n {
+ AppL10nEn([String locale = 'en']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Widgets';
+
+ @override
+ String get deskTabPainter => 'Painter';
+
+ @override
+ String get deskTabKnowledge => 'Knowledge';
+
+ @override
+ String get deskTabTools => 'Treasure';
+
+ @override
+ String get deskTabMine => 'About';
+
+ @override
+ String get messageBoard => 'Message Board';
+
+ @override
+ String get mobileTabWidgets => 'Widgets';
+
+ @override
+ String get mobileTabPainter => 'Painter';
+
+ @override
+ String get mobileTabKnowledge => 'Knowledge';
+
+ @override
+ String get mobileTabTools => 'Treasure';
+
+ @override
+ String get mobileTabMine => 'Mine';
+
+ @override
+ String get newBoard => 'New';
+
+ @override
+ String get news => 'News';
+
+ @override
+ String get moreNews => 'More News';
+}
diff --git a/lib/src/l10n/gen/app_l10n_es.dart b/lib/src/l10n/gen/app_l10n_es.dart
new file mode 100644
index 00000000..121c6f7d
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_es.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Spanish Castilian (`es`).
+class AppL10nEs extends AppL10n {
+ AppL10nEs([String locale = 'es']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Colección de widgets';
+
+ @override
+ String get deskTabPainter => 'Colección de dibujos';
+
+ @override
+ String get deskTabKnowledge => 'Centro de conocimiento';
+
+ @override
+ String get deskTabTools => 'Caja de herramientas';
+
+ @override
+ String get deskTabMine => 'Info App';
+
+ @override
+ String get messageBoard => 'Tablero de Mensajes';
+
+ @override
+ String get mobileTabWidgets => 'Widgets';
+
+ @override
+ String get mobileTabPainter => 'Dibujo';
+
+ @override
+ String get mobileTabKnowledge => 'Conocimiento';
+
+ @override
+ String get mobileTabTools => 'Herramientas';
+
+ @override
+ String get mobileTabMine => 'Mi';
+
+ @override
+ String get newBoard => 'Nuevo';
+
+ @override
+ String get news => 'Noticias';
+
+ @override
+ String get moreNews => 'Más noticias';
+}
diff --git a/lib/src/l10n/gen/app_l10n_fr.dart b/lib/src/l10n/gen/app_l10n_fr.dart
new file mode 100644
index 00000000..14d753ca
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_fr.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for French (`fr`).
+class AppL10nFr extends AppL10n {
+ AppL10nFr([String locale = 'fr']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Collection de widgets';
+
+ @override
+ String get deskTabPainter => 'Collection de dessins';
+
+ @override
+ String get deskTabKnowledge => 'Base de connaissances';
+
+ @override
+ String get deskTabTools => 'Boîte à outils';
+
+ @override
+ String get deskTabMine => 'Infos App';
+
+ @override
+ String get messageBoard => 'Tableau de messages';
+
+ @override
+ String get mobileTabWidgets => 'Widgets';
+
+ @override
+ String get mobileTabPainter => 'Dessin';
+
+ @override
+ String get mobileTabKnowledge => 'Connaissances';
+
+ @override
+ String get mobileTabTools => 'Outils';
+
+ @override
+ String get mobileTabMine => 'Moi';
+
+ @override
+ String get newBoard => 'Nouveau';
+
+ @override
+ String get news => 'Actualités';
+
+ @override
+ String get moreNews => 'Plus d\'actualités';
+}
diff --git a/lib/src/l10n/gen/app_l10n_it.dart b/lib/src/l10n/gen/app_l10n_it.dart
new file mode 100644
index 00000000..20d3e47c
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_it.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Italian (`it`).
+class AppL10nIt extends AppL10n {
+ AppL10nIt([String locale = 'it']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Raccolta widget';
+
+ @override
+ String get deskTabPainter => 'Raccolta disegni';
+
+ @override
+ String get deskTabKnowledge => 'Hub conoscitivo';
+
+ @override
+ String get deskTabTools => 'Cassetta degli attrezzi';
+
+ @override
+ String get deskTabMine => 'Info App';
+
+ @override
+ String get messageBoard => 'Bacheca';
+
+ @override
+ String get mobileTabWidgets => 'Widget';
+
+ @override
+ String get mobileTabPainter => 'Disegno';
+
+ @override
+ String get mobileTabKnowledge => 'Conoscenza';
+
+ @override
+ String get mobileTabTools => 'Strumenti';
+
+ @override
+ String get mobileTabMine => 'Io';
+
+ @override
+ String get newBoard => 'Nuovo';
+
+ @override
+ String get news => 'Notizie';
+
+ @override
+ String get moreNews => 'Altre notizie';
+}
diff --git a/lib/src/l10n/gen/app_l10n_ja.dart b/lib/src/l10n/gen/app_l10n_ja.dart
new file mode 100644
index 00000000..d55fc327
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_ja.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Japanese (`ja`).
+class AppL10nJa extends AppL10n {
+ AppL10nJa([String locale = 'ja']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'ウィジェット集';
+
+ @override
+ String get deskTabPainter => '描画集';
+
+ @override
+ String get deskTabKnowledge => 'ナレッジハブ';
+
+ @override
+ String get deskTabTools => 'ツールボックス';
+
+ @override
+ String get deskTabMine => 'アプリ情報';
+
+ @override
+ String get messageBoard => '掲示板';
+
+ @override
+ String get mobileTabWidgets => 'ウィジェット';
+
+ @override
+ String get mobileTabPainter => '描画';
+
+ @override
+ String get mobileTabKnowledge => '知識';
+
+ @override
+ String get mobileTabTools => 'ツール';
+
+ @override
+ String get mobileTabMine => 'マイ';
+
+ @override
+ String get newBoard => '新規作成';
+
+ @override
+ String get news => '最新情報';
+
+ @override
+ String get moreNews => 'もっと見る';
+}
diff --git a/lib/src/l10n/gen/app_l10n_ko.dart b/lib/src/l10n/gen/app_l10n_ko.dart
new file mode 100644
index 00000000..920b7a29
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_ko.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Korean (`ko`).
+class AppL10nKo extends AppL10n {
+ AppL10nKo([String locale = 'ko']) : super(locale);
+
+ @override
+ String get deskTabWidgets => '위젯 모음집';
+
+ @override
+ String get deskTabPainter => '그림 모음집';
+
+ @override
+ String get deskTabKnowledge => '지식 허브';
+
+ @override
+ String get deskTabTools => '도구 상자';
+
+ @override
+ String get deskTabMine => '앱 정보';
+
+ @override
+ String get messageBoard => '게시판';
+
+ @override
+ String get mobileTabWidgets => '위젯';
+
+ @override
+ String get mobileTabPainter => '그리기';
+
+ @override
+ String get mobileTabKnowledge => '지식';
+
+ @override
+ String get mobileTabTools => '도구';
+
+ @override
+ String get mobileTabMine => '내 정보';
+
+ @override
+ String get newBoard => '새 글';
+
+ @override
+ String get news => '최신 소식';
+
+ @override
+ String get moreNews => '더 보기';
+}
diff --git a/lib/src/l10n/gen/app_l10n_pt.dart b/lib/src/l10n/gen/app_l10n_pt.dart
new file mode 100644
index 00000000..ba255d47
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_pt.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Portuguese (`pt`).
+class AppL10nPt extends AppL10n {
+ AppL10nPt([String locale = 'pt']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Coleção de widgets';
+
+ @override
+ String get deskTabPainter => 'Coleção de desenhos';
+
+ @override
+ String get deskTabKnowledge => 'Hub de conhecimento';
+
+ @override
+ String get deskTabTools => 'Caixa de ferramentas';
+
+ @override
+ String get deskTabMine => 'Info App';
+
+ @override
+ String get messageBoard => 'Quadro de Mensagens';
+
+ @override
+ String get mobileTabWidgets => 'Widgets';
+
+ @override
+ String get mobileTabPainter => 'Desenho';
+
+ @override
+ String get mobileTabKnowledge => 'Conhecimento';
+
+ @override
+ String get mobileTabTools => 'Ferramentas';
+
+ @override
+ String get mobileTabMine => 'Meu';
+
+ @override
+ String get newBoard => 'Novo';
+
+ @override
+ String get news => 'Novidades';
+
+ @override
+ String get moreNews => 'Mais novidades';
+}
diff --git a/lib/src/l10n/gen/app_l10n_ru.dart b/lib/src/l10n/gen/app_l10n_ru.dart
new file mode 100644
index 00000000..7f00e6c9
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_ru.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Russian (`ru`).
+class AppL10nRu extends AppL10n {
+ AppL10nRu([String locale = 'ru']) : super(locale);
+
+ @override
+ String get deskTabWidgets => 'Коллекция виджетов';
+
+ @override
+ String get deskTabPainter => 'Коллекция рисунков';
+
+ @override
+ String get deskTabKnowledge => 'База знаний';
+
+ @override
+ String get deskTabTools => 'Инструменты';
+
+ @override
+ String get deskTabMine => 'Информация';
+
+ @override
+ String get messageBoard => 'Доска сообщений';
+
+ @override
+ String get mobileTabWidgets => 'Виджеты';
+
+ @override
+ String get mobileTabPainter => 'Рисование';
+
+ @override
+ String get mobileTabKnowledge => 'Знания';
+
+ @override
+ String get mobileTabTools => 'Инструменты';
+
+ @override
+ String get mobileTabMine => 'Мои';
+
+ @override
+ String get newBoard => 'Создать';
+
+ @override
+ String get news => 'Новости';
+
+ @override
+ String get moreNews => 'Больше новостей';
+}
diff --git a/lib/src/l10n/gen/app_l10n_zh.dart b/lib/src/l10n/gen/app_l10n_zh.dart
new file mode 100644
index 00000000..2e2086d1
--- /dev/null
+++ b/lib/src/l10n/gen/app_l10n_zh.dart
@@ -0,0 +1,52 @@
+// ignore: unused_import
+import 'package:intl/intl.dart' as intl;
+import 'app_l10n.dart';
+
+// ignore_for_file: type=lint
+
+/// The translations for Chinese (`zh`).
+class AppL10nZh extends AppL10n {
+ AppL10nZh([String locale = 'zh']) : super(locale);
+
+ @override
+ String get deskTabWidgets => '组件集录';
+
+ @override
+ String get deskTabPainter => '绘制集录';
+
+ @override
+ String get deskTabKnowledge => '知识集锦';
+
+ @override
+ String get deskTabTools => '工具宝箱';
+
+ @override
+ String get deskTabMine => '应用信息';
+
+ @override
+ String get messageBoard => '留言板';
+
+ @override
+ String get mobileTabWidgets => '组件';
+
+ @override
+ String get mobileTabPainter => '绘制';
+
+ @override
+ String get mobileTabKnowledge => '知识';
+
+ @override
+ String get mobileTabTools => '工具';
+
+ @override
+ String get mobileTabMine => '我的';
+
+ @override
+ String get newBoard => '新建 ';
+
+ @override
+ String get news => '最新资讯';
+
+ @override
+ String get moreNews => '查看更多';
+}
diff --git a/lib/src/l10n/locale_provider.dart b/lib/src/l10n/locale_provider.dart
new file mode 100644
index 00000000..7c631ee7
--- /dev/null
+++ b/lib/src/l10n/locale_provider.dart
@@ -0,0 +1,7 @@
+import 'package:flutter/material.dart';
+
+mixin LocalProvider {
+ Iterable>? get localizationsDelegates;
+
+ List get supportedLocales;
+}
diff --git a/lib/src/navigation/model/app_tab.dart b/lib/src/navigation/model/app_tab.dart
new file mode 100644
index 00000000..9417b7c3
--- /dev/null
+++ b/lib/src/navigation/model/app_tab.dart
@@ -0,0 +1,53 @@
+import 'package:app/app.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_unit/src/l10n/gen/app_l10n.dart';
+import 'package:tolyui/tolyui.dart';
+
+enum AppTab {
+ widgets('/widget', TolyIcon.icon_layout),
+ note('/note', Icons.note_alt_outlined),
+ knowledge('/knowledge', TolyIcon.icon_artifact),
+ painter('/painter', TolyIcon.dingzhi1),
+ tools('/tools', TolyIcon.icon_fast),
+ mine('/account', TolyIcon.yonghu);
+
+ final IconData icon;
+ final String path;
+
+ static List get mobileTabs => [
+ widgets,
+ painter,
+ knowledge,
+ note,
+ mine
+ ];
+
+ const AppTab(this.path, this.icon);
+
+ String label(AppL10n l10n) {
+ if (kAppEnv.isDesktopUI) {
+ return switch (this) {
+ AppTab.widgets => l10n.deskTabWidgets,
+ AppTab.painter => l10n.deskTabPainter,
+ AppTab.knowledge => l10n.deskTabKnowledge,
+ AppTab.tools => l10n.deskTabTools,
+ AppTab.mine => l10n.deskTabMine,
+ AppTab.note => l10n.messageBoard,
+ };
+ }
+ return switch (this) {
+ AppTab.widgets => l10n.mobileTabWidgets,
+ AppTab.painter => l10n.mobileTabPainter,
+ AppTab.knowledge => l10n.mobileTabKnowledge,
+ AppTab.tools => l10n.mobileTabTools,
+ AppTab.mine => l10n.mobileTabMine,
+ AppTab.note => l10n.messageBoard,
+ };
+ }
+
+ IconMenu menu(AppL10n l10n) => IconMenu(icon,
+ label: label(l10n),
+ route: path,
+ );
+}
diff --git a/lib/src/navigation/router/app_route.dart b/lib/src/navigation/router/app_route.dart
new file mode 100644
index 00000000..8c42ff21
--- /dev/null
+++ b/lib/src/navigation/router/app_route.dart
@@ -0,0 +1,40 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_unit/src/l10n/gen/app_l10n.dart';
+import '../view/desktop/flutter_unit_desk_navigation.dart';
+
+import 'system/app.dart';
+import 'system/global.dart';
+import 'system/settings.dart';
+import 'widgets/collection_route.dart';
+import 'widgets/widgets_route.dart';
+import 'package:note/note.dart';
+
+RouteBase get appRoute {
+ List body = [
+ widgetsRoute,
+ noteRoute,
+ collectRoute,
+ settingsRoute,
+ GoRoute(
+ path: AppRoute.moreNews.path,
+ builder: (ctx, __) => NewsPage(
+ title: AppL10n.of(ctx).news,
+ ),
+ ),
+ ...systemRoutes,
+ ];
+ return GoRoute(
+ path: AppRoute.home.path,
+ redirect: (_, __) => null,
+ routes: [
+ ...globalRoutes,
+ if (kAppEnv.isDesktopUI)
+ ShellRoute(
+ builder: (_, __, Widget child) => AppDeskNavigation(content: child),
+ routes: body,
+ ),
+ if (!kAppEnv.isDesktopUI) ...body,
+ ],
+ );
+}
diff --git a/lib/src/navigation/router/system/app.dart b/lib/src/navigation/router/system/app.dart
new file mode 100644
index 00000000..79ab782e
--- /dev/null
+++ b/lib/src/navigation/router/system/app.dart
@@ -0,0 +1,44 @@
+import 'package:app/app.dart';
+import 'package:artifact/artifact.dart';
+import 'package:authentication/authentication.dart';
+import 'package:draw_system/draw_system.dart';
+import 'package:treasure_tools/treasure_tools.dart';
+
+List get systemRoutes => [
+ GoRoute(
+ path: AppRoute.dataManage.path,
+ builder: (_, __) => const DataManagePage(),
+ ),
+ GoRoute(
+ path: AppRoute.account.path,
+ builder: (_, __) => const DeskAccountPage(),
+ ),
+ GoRoute(
+ path: AppRoute.aboutApp.path,
+ builder: (_, __) => const AboutAppPage(),
+ ),
+ GoRoute(
+ path: AppRoute.aboutMe.path,
+ builder: (_, __) => const AboutMePage(),
+ ),
+ GoRoute(
+ path: AppRoute.supportMe.path,
+ builder: (_, __) => const SupportMe(),
+ ),
+ if (kAppEnv.isDesktopUI) ...deskTopRoutes
+ ];
+
+List get deskTopRoutes => [
+ GoRoute(
+ path: AppRoute.knowledge.path,
+ builder: (_, __) => const DeskKnowledgePage(),
+ ),
+ GoRoute(
+ path: AppRoute.painter.path,
+ builder: (_, __) => const GalleryUnit(),
+ ),
+ GoRoute(
+ path: AppRoute.tools.path,
+ builder: (_, __) => const CodeGenPage(),
+ ),
+ ];
diff --git a/lib/src/navigation/router/system/global.dart b/lib/src/navigation/router/system/global.dart
new file mode 100644
index 00000000..d7c1c0f3
--- /dev/null
+++ b/lib/src/navigation/router/system/global.dart
@@ -0,0 +1,17 @@
+import 'package:app/app.dart';
+import '../../../starter/fx_application.dart';
+
+List get globalRoutes => [
+ GoRoute(
+ path: AppRoute.splash.path,
+ builder: (_, __) => const FlutterUnitSplash(),
+ ),
+ GoRoute(
+ path: AppRoute.startError.path,
+ builder: (_, GoRouterState state) => AppStartErrorPage(error: state.extra),
+ ),
+ GoRoute(
+ path: AppRoute.globalError.path,
+ builder: (_, GoRouterState state) => AppStartErrorPage(error: state.extra),
+ ),
+ ];
diff --git a/lib/src/navigation/router/system/settings.dart b/lib/src/navigation/router/system/settings.dart
new file mode 100644
index 00000000..820cd1dd
--- /dev/null
+++ b/lib/src/navigation/router/system/settings.dart
@@ -0,0 +1,28 @@
+import 'package:app/app.dart';
+
+GoRoute get settingsRoute => GoRoute(
+ path: AppRoute.settings.path,
+ builder: (_, __) => const SettingPage(),
+ routes: [
+ GoRoute(
+ path: AppRoute.darkModel.path,
+ builder: (_, __) => const ThemeModelSetting(),
+ ),
+ GoRoute(
+ path: AppRoute.codeStyle.path,
+ builder: (_, __) => const CodeStyleSettingPage(),
+ ),
+ GoRoute(
+ path: AppRoute.themeColor.path,
+ builder: (_, __) => const ThemeColorSettingPage(),
+ ),
+ GoRoute(
+ path: AppRoute.fontSetting.path,
+ builder: (_, __) => const FontSettingPage(),
+ ),
+ GoRoute(
+ path: AppRoute.version.path,
+ builder: (_, __) => const VersionInfo(),
+ ),
+ ],
+ );
diff --git a/lib/src/navigation/router/widgets/collection_route.dart b/lib/src/navigation/router/widgets/collection_route.dart
new file mode 100644
index 00000000..9b34deec
--- /dev/null
+++ b/lib/src/navigation/router/widgets/collection_route.dart
@@ -0,0 +1,29 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:widget_module/widget_module.dart';
+import 'package:note/note.dart';
+
+GoRoute get collectRoute => GoRoute(
+ path: AppRoute.collection.path,
+ builder: (_, __) => const CollectPageAdapter(),
+ routes: [
+ GoRoute(path: AppRoute.collectionDetail.path, builder: collectionDetailBuilder),
+ ],
+);
+
+GoRoute get noteRoute => GoRoute(
+ path: AppRoute.note.path,
+ builder: (_, __) => ArtSysScope(child: const ArticleAdmin()),
+ // routes: [
+ // GoRoute(path: AppRoute.collectionDetail.path, builder: collectionDetailBuilder),
+ // ],
+);
+
+Widget collectionDetailBuilder(BuildContext context, GoRouterState state) {
+ Object? extra = state.extra;
+ CategoryModel? model;
+ if (extra is CategoryModel) {
+ model = extra;
+ }
+ return CategoryShow(model: model!);
+}
diff --git a/lib/src/navigation/router/widgets/widgets_route.dart b/lib/src/navigation/router/widgets/widgets_route.dart
new file mode 100644
index 00000000..125fec83
--- /dev/null
+++ b/lib/src/navigation/router/widgets/widgets_route.dart
@@ -0,0 +1,39 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:widget_module/widget_module.dart';
+
+import '../../view/mobile/news.dart';
+import '../../view/mobile/unit_navigation.dart';
+
+GoRoute get widgetsRoute => GoRoute(
+ path: AppRoute.widget.path,
+ builder: (_, __) {
+ if (kAppEnv.isDesktopUI) {
+ return const DeskWidgetPanel(
+ header: NewsHeader(),
+ );
+ }
+ return const UnitPhoneNavigation();
+ },
+ routes: [
+ GoRoute(path: AppRoute.widgetDetail.path, builder: widgetDetailBuilder),
+ ],
+ );
+
+Widget widgetDetailBuilder(BuildContext context, GoRouterState state) {
+ Object? extra = state.extra;
+ String? widgetName = state.pathParameters['name'];
+
+ WidgetModel? model;
+ if (extra is WidgetModel) {
+ model = extra;
+ }
+ if (kAppEnv.isDesktopUI) {
+ return DeskWidgetDetailPageScope(
+ model: model,
+ widgetName: widgetName,
+ );
+ }
+ assert(model != null);
+ return WidgetDetailPageScope(model: model!);
+}
diff --git a/lib/src/navigation/view/app_bloc_provider.dart b/lib/src/navigation/view/app_bloc_provider.dart
new file mode 100644
index 00000000..9c339a59
--- /dev/null
+++ b/lib/src/navigation/view/app_bloc_provider.dart
@@ -0,0 +1,50 @@
+import 'package:app/app.dart';
+import 'package:note/note.dart';
+import 'package:app_update/app_update.dart';
+import 'package:authentication/authentication.dart';
+import 'package:draw_system/draw_system.dart';
+import 'package:storage/storage.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:widget_module/widget_module.dart';
+
+/// create by 张风捷特烈 on 2020/4/28
+/// contact me by email 1981462002@qq.com
+/// 说明: Bloc提供器包裹层
+
+class AppBlocProvider extends StatefulWidget {
+ final Widget child;
+
+ const AppBlocProvider({Key? key, required this.child}) : super(key: key);
+
+ @override
+ State createState() => _AppBlocProviderState();
+}
+
+class _AppBlocProviderState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return MultiBlocProvider(
+ providers: [
+ // 全局 bloc : 维护应用存储状态、更新、认证
+ BlocProvider(
+ create: (_) => AuthBloc(repository: HttpAuthRepository())),
+ BlocProvider(create: (_) => AppConfigBloc()),
+ BlocProvider(
+ create: (_) => UpgradeBloc(api: UnitUpgradeApi())),
+ BlocProvider(create: (_) => UserBloc()),
+ BlocProvider(create: (_) => NewsBloc()..initByCache()),
+
+ BlocProvider(
+ create: (_) => GalleryUnitBloc()..loadGalleryInfo()),
+ ],
+ child: WidgetsBlocProvider(child: widget.child),
+ );
+ }
+
+ @override
+ void dispose() {
+ AppStorage().close();
+ super.dispose();
+ }
+}
diff --git a/lib/src/navigation/view/desktop/flutter_unit_desk_navigation.dart b/lib/src/navigation/view/desktop/flutter_unit_desk_navigation.dart
new file mode 100644
index 00000000..29a55ee6
--- /dev/null
+++ b/lib/src/navigation/view/desktop/flutter_unit_desk_navigation.dart
@@ -0,0 +1,75 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_unit/src/l10n/gen/app_l10n.dart';
+import 'package:flutter_unit/src/navigation/model/app_tab.dart';
+import 'package:flutter_unit/src/navigation/view/desktop/unit_shortcuts_scope.dart';
+import 'package:go_router/go_router.dart';
+import 'package:tolyui_navigation/tolyui_navigation.dart';
+import 'menu_bar_leading.dart';
+import 'menu_bar_tail.dart';
+import 'toly_unit_menu_cell.dart';
+class AppDeskNavigation extends StatelessWidget {
+ final Widget content;
+
+ const AppDeskNavigation({super.key, required this.content});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: UnitShortcutsScope(
+ child: Row(
+ children: [
+ const DragToMoveWrapper(child: DeskNavigationRail()),
+ Expanded(child: content),
+ ],
+ ),
+ ),
+ );
+ }
+}
+
+class DeskNavigationRail extends StatefulWidget {
+ const DeskNavigationRail({super.key});
+
+ @override
+ State createState() => _DeskNavigationRailState();
+}
+
+class _DeskNavigationRailState extends State {
+
+ @override
+ Widget build(BuildContext context) {
+ return TolyRailMenuBar(
+ cellBuilder: FlutterUnitMenuCell.create,
+ width: 140,
+ gap: 8,
+ padding: EdgeInsets.zero,
+ backgroundColor: const Color(0xff2C3036),
+ menus: deskNavBarMenus,
+ activeId: activePath,
+ enableWidthChange: false,
+ onSelected: context.go,
+ tail: (_) => const MenuBarTail(),
+ leading: (_) => const MenuBarLeading(),
+ );
+ }
+
+ late List deskNavBarMenus;
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ AppL10n l10n = AppL10n.of(context);
+ deskNavBarMenus = AppTab.values.map((e)=>e.menu(l10n)).toList();
+ }
+
+ final RegExp _segReg = RegExp(r'/\w+');
+
+ String? get activePath {
+ final String path = GoRouterState.of(context).uri.toString();
+ RegExpMatch? match = _segReg.firstMatch(path);
+ if (match == null) return null;
+ String? target = match.group(0);
+ return target;
+ }
+}
diff --git a/lib/src/navigation/view/desktop/locale_change_menu.dart b/lib/src/navigation/view/desktop/locale_change_menu.dart
new file mode 100644
index 00000000..54b1cf72
--- /dev/null
+++ b/lib/src/navigation/view/desktop/locale_change_menu.dart
@@ -0,0 +1,58 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:l10n/l10n.dart';
+import 'package:tolyui/tolyui.dart';
+import 'package:app/app.dart';
+
+class LocaleChangeMenu extends StatelessWidget {
+ const LocaleChangeMenu({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ List labels = Language.values.map((e) => e.label).toList();
+
+ DropMenuCellStyle lightStyle = const DropMenuCellStyle(
+ padding: EdgeInsets.symmetric(horizontal: 4, vertical: 0),
+ borderRadius: BorderRadius.all(Radius.circular(6)),
+ foregroundColor: Color(0xff1f1f1f),
+ backgroundColor: Colors.transparent,
+ disableColor: Color(0xffbfbfbf),
+ hoverBackgroundColor: Color(0xfff5f5f5),
+ hoverForegroundColor: Color(0xff1f1f1f),
+ textStyle: TextStyle(fontFamily: '微软雅黑', fontSize: 12,));
+ Language language =
+ context.select((AppConfigBloc bloc) => bloc.state.language);
+ int index = Language.values.indexOf(language);
+ return Stack(
+ alignment: Alignment.centerLeft,
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 6.0),
+ child: Icon(Icons.translate,color: Colors.white,size: 14),
+ ),
+ IconTheme(
+ data: const IconThemeData(color: Colors.white),
+ child: DefaultTextStyle(
+ style: const TextStyle(color: Colors.white),
+ child: TolySelect(
+ fontSize: 12,
+ cellStyle: lightStyle,
+ data: labels,
+ selectIndex: index,
+ iconSize: 16,
+ height: 26,
+ width: 100,
+ minWidth: 100,
+ maxHeight: 180,
+ padding: const EdgeInsets.only(right: 6,left: 24),
+ onSelected: (int index) async {
+ Language type = Language.values[index];
+ context.read().switchLanguage(type);
+ },
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/src/navigation/view/desktop/menu_bar_leading.dart b/lib/src/navigation/view/desktop/menu_bar_leading.dart
new file mode 100644
index 00000000..c3d097b0
--- /dev/null
+++ b/lib/src/navigation/view/desktop/menu_bar_leading.dart
@@ -0,0 +1,88 @@
+// Copyright 2014 The 张风捷特烈 . All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Author: 张风捷特烈
+// CreateTime: 2024-05-13
+// Contact Me: 1981462002@qq.com
+
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:toly_ui/toly_ui.dart';
+import 'package:tolyui/tolyui.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class MenuBarLeading extends StatelessWidget {
+ const MenuBarLeading({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: const EdgeInsets.only(top: 20, bottom: 8),
+ child: Column(
+ children: [
+ Wrap(
+ direction: Axis.vertical,
+ spacing: 8,
+ crossAxisAlignment: WrapCrossAlignment.center,
+ children: [
+ GestureDetector(
+ onDoubleTap: () {
+ sendEvent(1);
+ },
+ child: const CircleImage(
+ image: AssetImage('assets/images/icon_head.webp'),
+ size: 60,
+ ),
+ ),
+ const Text(
+ '张风捷特烈',
+ style: TextStyle(color: Colors.white70),
+ )
+ ],
+ ),
+ _buildIcons(),
+ const Divider(color: Colors.white, height: 1, endIndent: 20),
+ const SizedBox(height: 16),
+ ],
+ ),
+ );
+ }
+
+ final List menus = const [
+ LinkIconMenu(
+ TolyIcon.icon_github, "https://github.com/toly1994328/FlutterUnit"),
+ LinkIconMenu(TolyIcon.icon_juejin,
+ 'https://juejin.im/user/5b42c0656fb9a04fe727eb37'),
+ LinkIconMenu(TolyIcon.icon_item, 'http://toly1994.com/'),
+ ];
+
+ Widget _buildIcons() {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 8, top: 8),
+ child: Wrap(
+ spacing: 8,
+ children: menus
+ .map((menu) => TolyAction(
+ style: const ActionStyle.dark(),
+ onTap: menu.launch,
+ child: Icon(menu.icon, color: Colors.white, size: 22),
+ ))
+ .toList(),
+ ),
+ );
+ }
+}
+
+class LinkIconMenu {
+ final IconData icon;
+ final String url;
+
+ const LinkIconMenu(this.icon, this.url);
+
+ void launch() => _launchUrl(url);
+
+ void _launchUrl(String url) async {
+ if (!await launchUrl(Uri.parse(url))) {}
+ }
+}
diff --git a/lib/src/navigation/view/desktop/menu_bar_tail.dart b/lib/src/navigation/view/desktop/menu_bar_tail.dart
new file mode 100644
index 00000000..17b33129
--- /dev/null
+++ b/lib/src/navigation/view/desktop/menu_bar_tail.dart
@@ -0,0 +1,82 @@
+// Copyright 2014 The 张风捷特烈 . All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Author: 张风捷特烈
+// CreateTime: 2024-05-13
+// Contact Me: 1981462002@qq.com
+
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_unit/src/flutter_unit.dart';
+import 'package:go_router/go_router.dart';
+import 'package:toly_ui/toly_ui.dart';
+import 'package:tolyui/basic/basic.dart';
+
+import 'locale_change_menu.dart';
+import 'theme_model_switch_icon.dart';
+import 'package:app_update/app_update.dart';
+
+enum ActionType {
+ settings(path: '/settings'),
+ collection(path: '/collection');
+
+ final String path;
+
+ const ActionType({required this.path});
+}
+
+class MenuBarTail extends StatelessWidget {
+ const MenuBarTail({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ const Divider(indent: 20, color: Colors.white, height: 1),
+ const SizedBox(height: 8,),
+ const LocaleChangeMenu(),
+ Padding(
+ padding: const EdgeInsets.only(left: 8, right: 8,bottom: 8,top: 2),
+ child: Wrap(
+ crossAxisAlignment: WrapCrossAlignment.center,
+ spacing: 8,
+ children: [
+ const SettingIcon(),
+ TolyAction(
+ style: const ActionStyle.dark(),
+ onTap: () => context.push(ActionType.collection.path),
+ child: const Icon(
+ TolyIcon.icon_collect,
+ color: Colors.white,
+ size: 22,
+ ),
+ ),
+ const ThemeModelSwitchIcon(),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
+
+class SettingIcon extends StatelessWidget {
+ const SettingIcon({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ UpdateState state = context.watch().state;
+ Color tipColor = Colors.redAccent;
+ Widget child = TolyAction(
+ style: const ActionStyle.dark(),
+ onTap: () => context.push(ActionType.settings.path),
+ child: const Icon(Icons.settings, color: Colors.white, size: 22),
+ );
+ return switch (state) {
+ ShouldUpdateState() => Badge(backgroundColor: tipColor, child: child),
+ _ => child,
+ };
+ }
+}
diff --git a/lib/src/navigation/view/desktop/theme_model_switch_icon.dart b/lib/src/navigation/view/desktop/theme_model_switch_icon.dart
new file mode 100644
index 00000000..3aae39e6
--- /dev/null
+++ b/lib/src/navigation/view/desktop/theme_model_switch_icon.dart
@@ -0,0 +1,28 @@
+import 'package:app/app.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:tolyui/tolyui.dart';
+
+class ThemeModelSwitchIcon extends StatelessWidget {
+
+ const ThemeModelSwitchIcon({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ bool isDark = Theme.of(context).brightness == Brightness.dark;
+ return MouseRegion(
+ cursor: SystemMouseCursors.click,
+ child: TolyAction(
+ style: const ActionStyle.dark(),
+ onTap: (){
+ context.read().changeThemeMode(isDark?ThemeMode.light:ThemeMode.dark);
+ },
+ child: Icon(
+ !isDark?TolyIcon.dark:TolyIcon.wb_sunny,
+ color: Colors.white,
+ size: 22,
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/src/navigation/view/desktop/toly_unit_menu_cell.dart b/lib/src/navigation/view/desktop/toly_unit_menu_cell.dart
new file mode 100644
index 00000000..8c17403e
--- /dev/null
+++ b/lib/src/navigation/view/desktop/toly_unit_menu_cell.dart
@@ -0,0 +1,86 @@
+// Copyright 2014 The 张风捷特烈 . All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Author: 张风捷特烈
+// CreateTime: 2024-05-13
+// Contact Me: 1981462002@qq.com
+
+import 'package:flutter/material.dart';
+import 'package:tolyui/tolyui.dart';
+import 'package:tolyui_navigation/tolyui_navigation.dart';
+
+final Tween _widthTween = Tween(begin: 0.82, end: 0.95);
+final Tween _sizeTween = Tween(begin: 18.0, end: 22.0);
+final Tween _fontSizeTween = Tween(begin: 14.0, end: 15);
+
+class FlutterUnitMenuCell extends StatelessWidget {
+ final MenuMeta menu;
+ final bool enableTooltip;
+ final DisplayMeta display;
+
+ const FlutterUnitMenuCell.create(this.menu, this.display,
+ {super.key, this.enableTooltip = false});
+
+ Color? get foregroundColor =>
+ display.selected ? Colors.white : Colors.white70;
+
+ @override
+ Widget build(BuildContext context) {
+ double height = 42;
+
+ double anim = display.rate;
+ Color? color = ColorTween(
+ begin: Colors.white.withAlpha(33),
+ end: Theme.of(context).primaryColor)
+ .transform(anim);
+
+ double iconSize = _sizeTween.transform(anim);
+ double fontSize = _fontSizeTween.transform(anim);
+ IconData? icon;
+ if (menu is IconMenu) {
+ icon = (menu as IconMenu).icon;
+ }
+ TextStyle style = TextStyle(color: foregroundColor, fontSize: fontSize);
+ Radius radius = Radius.circular(height / 2);
+ BorderRadius br = BorderRadius.only(topRight: radius, bottomRight: radius);
+ Widget child = Container(
+ padding: EdgeInsets.only(left: 12),
+ alignment: Alignment.centerLeft,
+ decoration: BoxDecoration(color: color, borderRadius: br),
+ width: _widthTween.transform(anim) * 140,
+ height: height,
+ child: Row(
+ spacing: 6,
+ // crossAxisAlignment: WrapCrossAlignment.center,
+ children: [
+ Icon(icon, color: foregroundColor, size: iconSize),
+ Expanded(
+ child: Text(
+ menu.label,
+ style: style,
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ const SizedBox(
+ width: 2,
+ )
+ ],
+ ),
+ );
+
+ if (enableTooltip) {
+ child = TolyTooltip(
+ placement: Placement.right,
+ message: menu.label,
+ child: child,
+ );
+ }
+
+ return Align(
+ alignment: Alignment.centerLeft,
+ child: child,
+ );
+ }
+}
diff --git a/lib/src/navigation/view/desktop/unit_shortcuts_scope.dart b/lib/src/navigation/view/desktop/unit_shortcuts_scope.dart
new file mode 100644
index 00000000..96818bea
--- /dev/null
+++ b/lib/src/navigation/view/desktop/unit_shortcuts_scope.dart
@@ -0,0 +1,48 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:fx_trace/fx_trace.dart';
+import 'package:go_router/go_router.dart';
+import 'package:widget_module/widget_module.dart';
+
+class GlobalFind extends Intent {
+ const GlobalFind();
+}
+
+class UnitShortcutsScope extends StatefulWidget {
+ final Widget child;
+
+ const UnitShortcutsScope({super.key, required this.child});
+
+ @override
+ State createState() => _UnitShortcutsScopeState();
+}
+
+class _UnitShortcutsScopeState extends State
+ with FxEmitterMixin {
+ @override
+ Widget build(BuildContext context) {
+ return Shortcuts(
+ shortcuts: {
+ LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyF): const GlobalFind(),
+ },
+ child: Actions(
+ actions: >{
+ GlobalFind: CallbackAction(onInvoke: _onGlobalSearch),
+ },
+ child: widget.child,
+ ),
+ );
+ }
+
+ @override
+ void onEvent(FxEvent event) {
+ if (event is SelectWidgetEvent) {
+ context.push('/widget/detail/${event.name}', extra: event.model);
+ }
+ }
+
+ Object? _onGlobalSearch(GlobalFind intent) {
+ showDialog(context: context, builder: (_) => const GlobalFindDialog());
+ return null;
+ }
+}
diff --git a/lib/src/navigation/view/mobile/carousel.dart b/lib/src/navigation/view/mobile/carousel.dart
new file mode 100644
index 00000000..6802defa
--- /dev/null
+++ b/lib/src/navigation/view/mobile/carousel.dart
@@ -0,0 +1,236 @@
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:app/app.dart';
+import 'news.dart';
+
+typedef TypeWidgetBuilder = Widget Function(BuildContext context, T data);
+
+class Carousel extends StatefulWidget {
+ final List data;
+ final TypeWidgetBuilder itemBuilder;
+
+ const Carousel({
+ super.key,
+ required this.data,
+ required this.itemBuilder,
+ });
+
+ @override
+ State createState() => _CarouselState();
+}
+
+class _CarouselState