Compare commits
11 Commits
6716456b04
...
v1.0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7824c920b | ||
|
|
817ad978e2 | ||
|
|
1d59128e47 | ||
|
|
62537f5814 | ||
|
|
5f91160d9a | ||
|
|
64ee8189b1 | ||
|
|
665a51f962 | ||
|
|
bd77beb60a | ||
|
|
578bb926fa | ||
|
|
2c64038fda | ||
|
|
9a27ae8e69 |
17
README.md
@@ -44,3 +44,20 @@ iOS端暂无上架打算,用户自行下载main分支源码编译安装
|
|||||||
### 不支持的功能
|
### 不支持的功能
|
||||||
>* 应用设置
|
>* 应用设置
|
||||||
>* 通知设置
|
>* 通知设置
|
||||||
|
|
||||||
|
|
||||||
|
版本更新通知 https://t.me/qinglongapp
|
||||||
|
|
||||||
|
用于生成app的图标
|
||||||
|
|
||||||
|
flutter pub run flutter_launcher_icons:main
|
||||||
|
生成原生的启动页面
|
||||||
|
|
||||||
|
flutter pub run flutter_native_splash:create
|
||||||
|
修改app名称
|
||||||
|
|
||||||
|
flutter pub run flutter_app_name
|
||||||
|
|
||||||
|
生成json.jc.dart文件
|
||||||
|
flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="青龙"
|
android:label="青龙客户端"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 18 KiB |
BIN
assets/images/ql_splash.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
34
ios/.gitignore
vendored
@@ -1,34 +0,0 @@
|
|||||||
**/dgph
|
|
||||||
*.mode1v3
|
|
||||||
*.mode2v3
|
|
||||||
*.moved-aside
|
|
||||||
*.pbxuser
|
|
||||||
*.perspectivev3
|
|
||||||
**/*sync/
|
|
||||||
.sconsign.dblite
|
|
||||||
.tags*
|
|
||||||
**/.vagrant/
|
|
||||||
**/DerivedData/
|
|
||||||
Icon?
|
|
||||||
**/Pods/
|
|
||||||
**/.symlinks/
|
|
||||||
profile
|
|
||||||
xcuserdata
|
|
||||||
**/.generated/
|
|
||||||
Flutter/App.framework
|
|
||||||
Flutter/Flutter.framework
|
|
||||||
Flutter/Flutter.podspec
|
|
||||||
Flutter/Generated.xcconfig
|
|
||||||
Flutter/ephemeral/
|
|
||||||
Flutter/app.flx
|
|
||||||
Flutter/app.zip
|
|
||||||
Flutter/flutter_assets/
|
|
||||||
Flutter/flutter_export_environment.sh
|
|
||||||
ServiceDefinitions.json
|
|
||||||
Runner/GeneratedPluginRegistrant.*
|
|
||||||
|
|
||||||
# Exceptions to above rules.
|
|
||||||
!default.mode1v3
|
|
||||||
!default.mode2v3
|
|
||||||
!default.pbxuser
|
|
||||||
!default.perspectivev3
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>App</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>io.flutter.flutter.app</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>App</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>FMWK</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>MinimumOSVersion</key>
|
|
||||||
<string>9.0</string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
|
||||||
#include "Generated.xcconfig"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
|
||||||
#include "Generated.xcconfig"
|
|
||||||
41
ios/Podfile
@@ -1,41 +0,0 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
|
||||||
# platform :ios, '9.0'
|
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
|
||||||
|
|
||||||
project 'Runner', {
|
|
||||||
'Debug' => :debug,
|
|
||||||
'Profile' => :release,
|
|
||||||
'Release' => :release,
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutter_root
|
|
||||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
|
||||||
unless File.exist?(generated_xcode_build_settings_path)
|
|
||||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
|
||||||
end
|
|
||||||
|
|
||||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
|
||||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
|
||||||
return matches[1].strip if matches
|
|
||||||
end
|
|
||||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
|
||||||
end
|
|
||||||
|
|
||||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
|
||||||
|
|
||||||
flutter_ios_podfile_setup
|
|
||||||
|
|
||||||
target 'Runner' do
|
|
||||||
use_frameworks!
|
|
||||||
use_modular_headers!
|
|
||||||
|
|
||||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
|
||||||
end
|
|
||||||
|
|
||||||
post_install do |installer|
|
|
||||||
installer.pods_project.targets.each do |target|
|
|
||||||
flutter_additional_ios_build_settings(target)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- flutter_native_splash (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- fluttertoast (0.0.2):
|
|
||||||
- Flutter
|
|
||||||
- Toast
|
|
||||||
- move_to_background (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- package_info_plus (0.4.5):
|
|
||||||
- Flutter
|
|
||||||
- path_provider_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Toast (4.0.0)
|
|
||||||
- url_launcher_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- Flutter (from `Flutter`)
|
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
|
||||||
- move_to_background (from `.symlinks/plugins/move_to_background/ios`)
|
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
|
||||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- Toast
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
Flutter:
|
|
||||||
:path: Flutter
|
|
||||||
flutter_native_splash:
|
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
|
||||||
fluttertoast:
|
|
||||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
|
||||||
move_to_background:
|
|
||||||
:path: ".symlinks/plugins/move_to_background/ios"
|
|
||||||
package_info_plus:
|
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
|
||||||
path_provider_ios:
|
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
|
||||||
shared_preferences_ios:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_ios/ios"
|
|
||||||
url_launcher_ios:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
|
||||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
|
||||||
fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037
|
|
||||||
move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d
|
|
||||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
|
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
|
||||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
|
||||||
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
|
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
|
||||||
|
|
||||||
COCOAPODS: 1.11.2
|
|
||||||
@@ -1,554 +0,0 @@
|
|||||||
// !$*UTF8*$!
|
|
||||||
{
|
|
||||||
archiveVersion = 1;
|
|
||||||
classes = {
|
|
||||||
};
|
|
||||||
objectVersion = 51;
|
|
||||||
objects = {
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
|
||||||
2861C45503C8372CCC7FCAA2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0C7852E889B34711E51EF29 /* Pods_Runner.framework */; };
|
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
|
||||||
/* End PBXBuildFile section */
|
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
|
||||||
isa = PBXCopyFilesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
dstPath = "";
|
|
||||||
dstSubfolderSpec = 10;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
name = "Embed Frameworks";
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
|
||||||
08A8D0920911B337FB46E8F3 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
|
||||||
423DC651AE7A04B8898F3FDB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
||||||
D8C98252A2BD23DF365AF3A8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
E0C7852E889B34711E51EF29 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
/* End PBXFileReference section */
|
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
2861C45503C8372CCC7FCAA2 /* Pods_Runner.framework in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXFrameworksBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
|
||||||
80959B63BA92AC28CD093868 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
E0C7852E889B34711E51EF29 /* Pods_Runner.framework */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
|
||||||
);
|
|
||||||
name = Flutter;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146E51CF9000F007C117D = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
|
||||||
BA4BC66201CBD612BFBB5DAE /* Pods */,
|
|
||||||
80959B63BA92AC28CD093868 /* Frameworks */,
|
|
||||||
);
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146EF1CF9000F007C117D /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
|
||||||
97C147021CF9000F007C117D /* Info.plist */,
|
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
|
||||||
);
|
|
||||||
path = Runner;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
BA4BC66201CBD612BFBB5DAE /* Pods */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D8C98252A2BD23DF365AF3A8 /* Pods-Runner.debug.xcconfig */,
|
|
||||||
423DC651AE7A04B8898F3FDB /* Pods-Runner.release.xcconfig */,
|
|
||||||
08A8D0920911B337FB46E8F3 /* Pods-Runner.profile.xcconfig */,
|
|
||||||
);
|
|
||||||
path = Pods;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
|
||||||
buildPhases = (
|
|
||||||
FD0948CDBEBEC8A5B7ABF83F /* [CP] Check Pods Manifest.lock */,
|
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
|
||||||
C4AE37104D47B22A99900CA3 /* [CP] Embed Pods Frameworks */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = Runner;
|
|
||||||
productName = Runner;
|
|
||||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
|
||||||
productType = "com.apple.product-type.application";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
|
||||||
isa = PBXProject;
|
|
||||||
attributes = {
|
|
||||||
LastUpgradeCheck = 1300;
|
|
||||||
ORGANIZATIONNAME = "";
|
|
||||||
TargetAttributes = {
|
|
||||||
97C146ED1CF9000F007C117D = {
|
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
|
||||||
LastSwiftMigration = 1100;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
|
||||||
compatibilityVersion = "Xcode 9.3";
|
|
||||||
developmentRegion = en;
|
|
||||||
hasScannedForEncodings = 0;
|
|
||||||
knownRegions = (
|
|
||||||
en,
|
|
||||||
Base,
|
|
||||||
);
|
|
||||||
mainGroup = 97C146E51CF9000F007C117D;
|
|
||||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
|
||||||
projectDirPath = "";
|
|
||||||
projectRoot = "";
|
|
||||||
targets = (
|
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
/* End PBXProject section */
|
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXResourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Thin Binary";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
|
||||||
};
|
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Run Script";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
|
||||||
};
|
|
||||||
C4AE37104D47B22A99900CA3 /* [CP] Embed Pods Frameworks */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Embed Pods Frameworks";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
FD0948CDBEBEC8A5B7ABF83F /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
|
||||||
isa = PBXVariantGroup;
|
|
||||||
children = (
|
|
||||||
97C146FB1CF9000F007C117D /* Base */,
|
|
||||||
);
|
|
||||||
name = Main.storyboard;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
|
||||||
isa = PBXVariantGroup;
|
|
||||||
children = (
|
|
||||||
97C147001CF9000F007C117D /* Base */,
|
|
||||||
);
|
|
||||||
name = LaunchScreen.storyboard;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXVariantGroup section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
|
||||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Profile;
|
|
||||||
};
|
|
||||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.master.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Profile;
|
|
||||||
};
|
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
ENABLE_TESTABILITY = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
97C147041CF9000F007C117D /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_COMMA = YES;
|
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
97C147061CF9000F007C117D /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.master.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
97C147071CF9000F007C117D /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
||||||
CLANG_ENABLE_MODULES = YES;
|
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
|
||||||
DEVELOPMENT_TEAM = MKUK6TT46Z;
|
|
||||||
ENABLE_BITCODE = NO;
|
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"@executable_path/Frameworks",
|
|
||||||
);
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = work.newtab.qinglongApp;
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
/* End XCBuildConfiguration section */
|
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
97C147031CF9000F007C117D /* Debug */,
|
|
||||||
97C147041CF9000F007C117D /* Release */,
|
|
||||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
97C147061CF9000F007C117D /* Debug */,
|
|
||||||
97C147071CF9000F007C117D /* Release */,
|
|
||||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
|
||||||
};
|
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "self:">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEDidComputeMac32BitWarning</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>PreviewsEnabled</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1300"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<MacroExpansion>
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</MacroExpansion>
|
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Profile"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
|
||||||
BuildableName = "Runner.app"
|
|
||||||
BlueprintName = "Runner"
|
|
||||||
ReferencedContainer = "container:Runner.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
10
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "group:Runner.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
<FileRef
|
|
||||||
location = "group:Pods/Pods.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEDidComputeMac32BitWarning</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>PreviewsEnabled</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import UIKit
|
|
||||||
import Flutter
|
|
||||||
|
|
||||||
@UIApplicationMain
|
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
|
||||||
override func application(
|
|
||||||
_ application: UIApplication,
|
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
||||||
) -> Bool {
|
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-20x20@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-29x29@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-40x40@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-60x60@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "60x60",
|
|
||||||
"idiom" : "iphone",
|
|
||||||
"filename" : "Icon-App-60x60@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "20x20",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-20x20@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "29x29",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-29x29@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "40x40",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-40x40@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "76x76",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-76x76@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "83.5x83.5",
|
|
||||||
"idiom" : "ipad",
|
|
||||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size" : "1024x1024",
|
|
||||||
"idiom" : "ios-marketing",
|
|
||||||
"filename" : "Icon-App-1024x1024@1x.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 647 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "background.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filename" : "darkbackground.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appearances" : [
|
|
||||||
{
|
|
||||||
"appearance" : "luminosity",
|
|
||||||
"value" : "dark"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 70 B |
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "LaunchImage@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB |
@@ -1,5 +0,0 @@
|
|||||||
# Launch Screen Assets
|
|
||||||
|
|
||||||
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
|
||||||
|
|
||||||
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
|
||||||
</dependencies>
|
|
||||||
<scenes>
|
|
||||||
<!--View Controller-->
|
|
||||||
<scene sceneID="EHf-IW-A2E">
|
|
||||||
<objects>
|
|
||||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
|
||||||
<layoutGuides>
|
|
||||||
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
|
||||||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
|
||||||
</layoutGuides>
|
|
||||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
|
|
||||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
|
|
||||||
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
|
|
||||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="53" y="375"/>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
<resources>
|
|
||||||
<image name="LaunchImage" width="240" height="240"/>
|
|
||||||
<image name="LaunchBackground" width="1" height="1"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="iOS"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
|
||||||
</dependencies>
|
|
||||||
<scenes>
|
|
||||||
<!--Flutter View Controller-->
|
|
||||||
<scene sceneID="tne-QT-ifu">
|
|
||||||
<objects>
|
|
||||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
|
||||||
<layoutGuides>
|
|
||||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
|
||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
|
||||||
</layoutGuides>
|
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
|
||||||
</document>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
||||||
<key>CFBundleDisplayName</key>
|
|
||||||
<string>青龙</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>青龙</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>APPL</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
|
||||||
<key>CFBundleSignature</key>
|
|
||||||
<string>????</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
|
||||||
<key>LSRequiresIPhoneOS</key>
|
|
||||||
<true/>
|
|
||||||
<key>UILaunchStoryboardName</key>
|
|
||||||
<string>LaunchScreen</string>
|
|
||||||
<key>UIMainStoryboardFile</key>
|
|
||||||
<string>Main</string>
|
|
||||||
<key>UIStatusBarHidden</key>
|
|
||||||
<false/>
|
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
|
||||||
<array>
|
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
||||||
</array>
|
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#import "GeneratedPluginRegistrant.h"
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:qinglong_app/base/http/http.dart';
|
import 'package:qinglong_app/base/http/http.dart';
|
||||||
|
import 'package:qinglong_app/base/http/url.dart';
|
||||||
|
import 'package:qinglong_app/main.dart';
|
||||||
import 'package:qinglong_app/module/config/config_bean.dart';
|
import 'package:qinglong_app/module/config/config_bean.dart';
|
||||||
import 'package:qinglong_app/module/env/env_bean.dart';
|
import 'package:qinglong_app/module/env/env_bean.dart';
|
||||||
import 'package:qinglong_app/module/home/system_bean.dart';
|
import 'package:qinglong_app/module/home/system_bean.dart';
|
||||||
@@ -9,9 +11,7 @@ import 'package:qinglong_app/module/others/login_log/login_log_bean.dart';
|
|||||||
import 'package:qinglong_app/module/others/scripts/script_bean.dart';
|
import 'package:qinglong_app/module/others/scripts/script_bean.dart';
|
||||||
import 'package:qinglong_app/module/others/task_log/task_log_bean.dart';
|
import 'package:qinglong_app/module/others/task_log/task_log_bean.dart';
|
||||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||||
|
import 'package:qinglong_app/utils/utils.dart';
|
||||||
import '../../utils/utils.dart';
|
|
||||||
import 'url.dart';
|
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
static Future<HttpResponse<SystemBean>> system() async {
|
static Future<HttpResponse<SystemBean>> system() async {
|
||||||
@@ -89,24 +89,21 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> startTasks(
|
static Future<HttpResponse<NullResponse>> startTasks(List<String> crons) async {
|
||||||
List<String> crons) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.runTasks,
|
Url.runTasks,
|
||||||
crons,
|
crons,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> stopTasks(
|
static Future<HttpResponse<NullResponse>> stopTasks(List<String> crons) async {
|
||||||
List<String> crons) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.stopTasks,
|
Url.stopTasks,
|
||||||
crons,
|
crons,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> updatePassword(
|
static Future<HttpResponse<NullResponse>> updatePassword(String name, String password) async {
|
||||||
String name, String password) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.updatePassword,
|
Url.updatePassword,
|
||||||
{
|
{
|
||||||
@@ -124,15 +121,19 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> addTask(
|
static Future<HttpResponse<NullResponse>> addTask(
|
||||||
String name, String command, String cron,
|
String name,
|
||||||
{String? id}) async {
|
String command,
|
||||||
var data = {"name": name, "command": command, "schedule": cron};
|
String cron, {
|
||||||
|
int? id,
|
||||||
|
String? nId,
|
||||||
|
}) async {
|
||||||
|
var data = <String, dynamic>{"name": name, "command": command, "schedule": cron};
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null || nId != null) {
|
||||||
if (Utils.isUpperVersion()) {
|
if (id != null) {
|
||||||
data["id"] = id;
|
data["id"] = id;
|
||||||
} else {
|
} else if (nId != null) {
|
||||||
data["_id"] = id;
|
data["_id"] = nId;
|
||||||
}
|
}
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addTask,
|
Url.addTask,
|
||||||
@@ -194,8 +195,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> saveFile(
|
static Future<HttpResponse<NullResponse>> saveFile(String name, String content) async {
|
||||||
String name, String content) async {
|
|
||||||
return await Http.post<NullResponse>(
|
return await Http.post<NullResponse>(
|
||||||
Url.saveFile,
|
Url.saveFile,
|
||||||
{"content": content, "name": name},
|
{"content": content, "name": name},
|
||||||
@@ -231,21 +231,24 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> addEnv(
|
static Future<HttpResponse<NullResponse>> addEnv(
|
||||||
String name, String value, String remarks,
|
String name,
|
||||||
{String? id}) async {
|
String value,
|
||||||
var data = {
|
String remarks, {
|
||||||
|
int? id,
|
||||||
|
String? nId,
|
||||||
|
}) async {
|
||||||
|
var data = <String, dynamic>{
|
||||||
"value": value,
|
"value": value,
|
||||||
"remarks": remarks,
|
"remarks": remarks,
|
||||||
"name": name,
|
"name": name,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null || nId != null) {
|
||||||
if (Utils.isUpperVersion()) {
|
if (id != null) {
|
||||||
data["id"] = id;
|
data["id"] = id;
|
||||||
} else {
|
} else if (nId != null) {
|
||||||
data["_id"] = id;
|
data["_id"] = nId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.addEnv,
|
Url.addEnv,
|
||||||
data,
|
data,
|
||||||
@@ -257,8 +260,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> moveEnv(
|
static Future<HttpResponse<NullResponse>> moveEnv(String id, int fromIndex, int toIndex) async {
|
||||||
String id, int fromIndex, int toIndex) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.envMove(id),
|
Url.envMove(id),
|
||||||
{"fromIndex": fromIndex, "toIndex": toIndex},
|
{"fromIndex": fromIndex, "toIndex": toIndex},
|
||||||
@@ -273,26 +275,32 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<List<TaskLogBean>>> taskLog() async {
|
static Future<HttpResponse<List<TaskLogBean>>> taskLog() async {
|
||||||
return await Http.get<List<TaskLogBean>>(Url.taskLog, null,
|
return await Http.get<List<TaskLogBean>>(Url.taskLog, null, serializationName: Utils.isUpperVersion2_12_2() ? "data" : "dirs");
|
||||||
serializationName: "dirs");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<String>> taskLogDetail(String name) async {
|
static Future<HttpResponse<String>> taskLogDetail(String name, String path) async {
|
||||||
return await Http.get<String>(
|
if (Utils.isUpperVersion2_13_0()) {
|
||||||
Url.taskLogDetail + name,
|
return await Http.get<String>(
|
||||||
null,
|
Url.taskLogDetail + name + "?path=" + path,
|
||||||
);
|
null,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return await Http.get<String>(
|
||||||
|
Url.taskLogDetail + path + "/" + name,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<List<ScriptBean>>> scripts() async {
|
static Future<HttpResponse<List<ScriptBean>>> scripts() async {
|
||||||
|
//2.12.2以及以上版本,脚本路径url做了修改
|
||||||
return await Http.get<List<ScriptBean>>(
|
return await Http.get<List<ScriptBean>>(
|
||||||
Url.scripts,
|
Utils.isUpperVersion2_13_0() ? Url.scripts2 : Url.scripts,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> updateScript(
|
static Future<HttpResponse<NullResponse>> updateScript(String name, String path, String content) async {
|
||||||
String name, String path, String content) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.scriptDetail,
|
Url.scriptDetail,
|
||||||
{
|
{
|
||||||
@@ -303,8 +311,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> delScript(
|
static Future<HttpResponse<NullResponse>> delScript(String name, String path) async {
|
||||||
String name, String path) async {
|
|
||||||
return await Http.delete<NullResponse>(
|
return await Http.delete<NullResponse>(
|
||||||
Url.scriptDetail,
|
Url.scriptDetail,
|
||||||
{
|
{
|
||||||
@@ -314,8 +321,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<String>> scriptDetail(
|
static Future<HttpResponse<String>> scriptDetail(String name, String? path) async {
|
||||||
String name, String? path) async {
|
|
||||||
return await Http.get<String>(
|
return await Http.get<String>(
|
||||||
Url.scriptDetail + name,
|
Url.scriptDetail + name,
|
||||||
{
|
{
|
||||||
@@ -324,8 +330,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<List<DependencyBean>>> dependencies(
|
static Future<HttpResponse<List<DependencyBean>>> dependencies(String type) async {
|
||||||
String type) async {
|
|
||||||
return await Http.get<List<DependencyBean>>(
|
return await Http.get<List<DependencyBean>>(
|
||||||
Url.dependencies,
|
Url.dependencies,
|
||||||
{
|
{
|
||||||
@@ -334,8 +339,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> dependencyReinstall(
|
static Future<HttpResponse<NullResponse>> dependencyReinstall(String id) async {
|
||||||
String id) async {
|
|
||||||
return await Http.put<NullResponse>(
|
return await Http.put<NullResponse>(
|
||||||
Url.dependencies,
|
Url.dependencies,
|
||||||
[id],
|
[id],
|
||||||
@@ -349,8 +353,7 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> addDependency(
|
static Future<HttpResponse<NullResponse>> addDependency(String name, int type) async {
|
||||||
String name, int type) async {
|
|
||||||
return await Http.post<NullResponse>(
|
return await Http.post<NullResponse>(
|
||||||
Url.dependencies,
|
Url.dependencies,
|
||||||
[
|
[
|
||||||
@@ -362,6 +365,17 @@ class Api {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<HttpResponse<NullResponse>> addScript(String name, String path, String content) async {
|
||||||
|
return await Http.post<NullResponse>(
|
||||||
|
Url.addScript,
|
||||||
|
{
|
||||||
|
"filename": name,
|
||||||
|
"path": path,
|
||||||
|
"content": content,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<HttpResponse<NullResponse>> delDependency(String id) async {
|
static Future<HttpResponse<NullResponse>> delDependency(String id) async {
|
||||||
return await Http.delete<NullResponse>(
|
return await Http.delete<NullResponse>(
|
||||||
Url.dependencies,
|
Url.dependencies,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class TokenInterceptor extends Interceptor {
|
|||||||
@override
|
@override
|
||||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||||
options.headers["User-Agent"] =
|
options.headers["User-Agent"] =
|
||||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";
|
"qinglong_client";
|
||||||
|
|
||||||
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
options.headers["Content-Type"] = "application/json;charset=UTF-8";
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import '../../main.dart';
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
import '../userinfo_viewmodel.dart';
|
import 'package:qinglong_app/main.dart';
|
||||||
|
|
||||||
class Url {
|
class Url {
|
||||||
static get system => "/api/system";
|
|
||||||
|
|
||||||
static get login => "/api/user/login";
|
static get login => "/api/user/login";
|
||||||
|
|
||||||
|
static get system => "/api/system";
|
||||||
|
|
||||||
static get loginOld => "/api/login";
|
static get loginOld => "/api/login";
|
||||||
|
|
||||||
static get loginTwo => "/api/user/two-factor/login";
|
static get loginTwo => "/api/user/two-factor/login";
|
||||||
@@ -14,119 +14,70 @@ class Url {
|
|||||||
|
|
||||||
static const updatePassword = "/api/user";
|
static const updatePassword = "/api/user";
|
||||||
|
|
||||||
static get tasks => getIt<UserInfoViewModel>().useSecretLogined
|
static get tasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons" : "/api/crons";
|
||||||
? "/open/crons"
|
|
||||||
: "/api/crons";
|
|
||||||
|
|
||||||
static get runTasks => getIt<UserInfoViewModel>().useSecretLogined
|
static get runTasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/run" : "/api/crons/run";
|
||||||
? "/open/crons/run"
|
|
||||||
: "/api/crons/run";
|
|
||||||
|
|
||||||
static get stopTasks => getIt<UserInfoViewModel>().useSecretLogined
|
static get stopTasks => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/stop" : "/api/crons/stop";
|
||||||
? "/open/crons/stop"
|
|
||||||
: "/api/crons/stop";
|
|
||||||
|
|
||||||
static get taskDetail => getIt<UserInfoViewModel>().useSecretLogined
|
static get taskDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/" : "/api/crons/";
|
||||||
? "/open/crons/"
|
|
||||||
: "/api/crons/";
|
|
||||||
|
|
||||||
static get addTask => getIt<UserInfoViewModel>().useSecretLogined
|
static get addTask => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons" : "/api/crons";
|
||||||
? "/open/crons"
|
|
||||||
: "/api/crons";
|
|
||||||
|
|
||||||
static get pinTask => getIt<UserInfoViewModel>().useSecretLogined
|
static get pinTask => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/pin" : "/api/crons/pin";
|
||||||
? "/open/crons/pin"
|
|
||||||
: "/api/crons/pin";
|
|
||||||
|
|
||||||
static get unpinTask => getIt<UserInfoViewModel>().useSecretLogined
|
static get unpinTask => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/unpin" : "/api/crons/unpin";
|
||||||
? "/open/crons/unpin"
|
|
||||||
: "/api/crons/unpin";
|
|
||||||
|
|
||||||
static get enableTask => getIt<UserInfoViewModel>().useSecretLogined
|
static get enableTask => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/enable" : "/api/crons/enable";
|
||||||
? "/open/crons/enable"
|
|
||||||
: "/api/crons/enable";
|
|
||||||
|
|
||||||
static get disableTask => getIt<UserInfoViewModel>().useSecretLogined
|
static get disableTask => getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/disable" : "/api/crons/disable";
|
||||||
? "/open/crons/disable"
|
|
||||||
: "/api/crons/disable";
|
|
||||||
|
|
||||||
static get files => getIt<UserInfoViewModel>().useSecretLogined
|
static get files => getIt<UserInfoViewModel>().useSecretLogined ? "/open/configs/files" : "/api/configs/files";
|
||||||
? "/open/configs/files"
|
|
||||||
: "/api/configs/files";
|
|
||||||
|
|
||||||
static get configContent => getIt<UserInfoViewModel>().useSecretLogined
|
static get configContent => getIt<UserInfoViewModel>().useSecretLogined ? "/open/configs/" : "/api/configs/";
|
||||||
? "/open/configs/"
|
|
||||||
: "/api/configs/";
|
|
||||||
|
|
||||||
static get saveFile => getIt<UserInfoViewModel>().useSecretLogined
|
static get saveFile => getIt<UserInfoViewModel>().useSecretLogined ? "/open/configs/save" : "/api/configs/save";
|
||||||
? "/open/configs/save"
|
|
||||||
: "/api/configs/save";
|
|
||||||
|
|
||||||
static get envs =>
|
static get envs => getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
||||||
getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
|
||||||
|
|
||||||
static get addEnv =>
|
static get addEnv => getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
||||||
getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
|
||||||
|
|
||||||
static get delEnv =>
|
static get delEnv => getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
||||||
getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs" : "/api/envs";
|
|
||||||
|
|
||||||
static get disableEnvs => getIt<UserInfoViewModel>().useSecretLogined
|
static get disableEnvs => getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/disable" : "/api/envs/disable";
|
||||||
? "/open/envs/disable"
|
|
||||||
: "/api/envs/disable";
|
|
||||||
|
|
||||||
static get enableEnvs => getIt<UserInfoViewModel>().useSecretLogined
|
static get enableEnvs => getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/enable" : "/api/envs/enable";
|
||||||
? "/open/envs/enable"
|
|
||||||
: "/api/envs/enable";
|
|
||||||
|
|
||||||
static get loginLog => getIt<UserInfoViewModel>().useSecretLogined
|
static get loginLog => getIt<UserInfoViewModel>().useSecretLogined ? "/open/user/login-log" : "/api/user/login-log";
|
||||||
? "/open/user/login-log"
|
|
||||||
: "/api/user/login-log";
|
|
||||||
|
|
||||||
static get taskLog =>
|
static get taskLog => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs" : "/api/logs";
|
||||||
getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs" : "/api/logs";
|
|
||||||
|
|
||||||
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined
|
static get taskLogDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/logs/" : "/api/logs/";
|
||||||
? "/open/logs/"
|
|
||||||
: "/api/logs/";
|
|
||||||
|
|
||||||
static get scripts => getIt<UserInfoViewModel>().useSecretLogined
|
static get scripts => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/files" : "/api/scripts/files";
|
||||||
? "/open/scripts/files"
|
|
||||||
: "/api/scripts/files";
|
|
||||||
|
|
||||||
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined
|
static get scripts2 => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
? "/open/scripts"
|
|
||||||
: "/api/scripts";
|
|
||||||
|
|
||||||
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined
|
static get scriptUpdate => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
? "/open/scripts/"
|
|
||||||
: "/api/scripts/";
|
|
||||||
|
|
||||||
static get dependencies => getIt<UserInfoViewModel>().useSecretLogined
|
static get scriptDetail => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts/" : "/api/scripts/";
|
||||||
? "/open/dependencies"
|
|
||||||
: "/api/dependencies";
|
|
||||||
|
|
||||||
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined
|
static get dependencies => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies" : "/api/dependencies";
|
||||||
? "/open/dependencies/reinstall"
|
|
||||||
: "/api/dependencies/reinstall";
|
static get addScript => getIt<UserInfoViewModel>().useSecretLogined ? "/open/scripts" : "/api/scripts";
|
||||||
|
|
||||||
|
static get dependencyReinstall => getIt<UserInfoViewModel>().useSecretLogined ? "/open/dependencies/reinstall" : "/api/dependencies/reinstall";
|
||||||
|
|
||||||
static intimeLog(String cronId) {
|
static intimeLog(String cronId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/crons/$cronId/log" : "/api/crons/$cronId/log";
|
||||||
? "/open/crons/$cronId/log"
|
|
||||||
: "/api/crons/$cronId/log";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static envMove(String envId) {
|
static envMove(String envId) {
|
||||||
return getIt<UserInfoViewModel>().useSecretLogined
|
return getIt<UserInfoViewModel>().useSecretLogined ? "/open/envs/$envId/move" : "/api/envs/$envId/move";
|
||||||
? "/open/envs/$envId/move"
|
|
||||||
: "/api/envs/$envId/move";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool inWhiteList(String path) {
|
static bool inWhiteList(String path) {
|
||||||
if (path == login ||
|
if (path == login || path == loginByClientId || path == loginTwo || path == loginOld) {
|
||||||
path == loginByClientId ||
|
|
||||||
path == loginTwo ||
|
|
||||||
path == loginOld) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -138,7 +89,4 @@ class Url {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String checkUpdateUrl =
|
|
||||||
"https://raw.githubusercontent.com/qinglong-app/qinglong_app/main/version";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import 'package:qinglong_app/module/env/env_detail_page.dart';
|
|||||||
import 'package:qinglong_app/module/home/home_page.dart';
|
import 'package:qinglong_app/module/home/home_page.dart';
|
||||||
import 'package:qinglong_app/module/login/login_page.dart';
|
import 'package:qinglong_app/module/login/login_page.dart';
|
||||||
import 'package:qinglong_app/module/others/about_page.dart';
|
import 'package:qinglong_app/module/others/about_page.dart';
|
||||||
import 'package:qinglong_app/module/others/change_account_page.dart';
|
|
||||||
import 'package:qinglong_app/module/others/dependencies/add_dependency_page.dart';
|
import 'package:qinglong_app/module/others/dependencies/add_dependency_page.dart';
|
||||||
import 'package:qinglong_app/module/others/dependencies/dependency_page.dart';
|
import 'package:qinglong_app/module/others/dependencies/dependency_page.dart';
|
||||||
import 'package:qinglong_app/module/others/login_log/login_log_page.dart';
|
import 'package:qinglong_app/module/others/login_log/login_log_page.dart';
|
||||||
@@ -42,7 +41,6 @@ class Routes {
|
|||||||
static const String routeUpdatePassword = "/updatePassword";
|
static const String routeUpdatePassword = "/updatePassword";
|
||||||
static const String routeAbout = "/about";
|
static const String routeAbout = "/about";
|
||||||
static const String routeTheme = "/theme";
|
static const String routeTheme = "/theme";
|
||||||
static const String routeChangeAccount = "/changeAccount";
|
|
||||||
|
|
||||||
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
||||||
switch (settings.name) {
|
switch (settings.name) {
|
||||||
@@ -105,7 +103,8 @@ class Routes {
|
|||||||
case routeTaskLogDetail:
|
case routeTaskLogDetail:
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => TaskLogDetailPage(
|
builder: (context) => TaskLogDetailPage(
|
||||||
title: settings.arguments as String,
|
title: (settings.arguments as Map)['title'],
|
||||||
|
path: (settings.arguments as Map)['path'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
case routeScriptDetail:
|
case routeScriptDetail:
|
||||||
@@ -139,10 +138,6 @@ class Routes {
|
|||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => const ThemePage(),
|
builder: (context) => const ThemePage(),
|
||||||
);
|
);
|
||||||
case routeChangeAccount:
|
|
||||||
return CupertinoPageRoute(
|
|
||||||
builder: (context) => const ChangeAccountPage(),
|
|
||||||
);
|
|
||||||
case routeScriptUpdate:
|
case routeScriptUpdate:
|
||||||
return CupertinoPageRoute(
|
return CupertinoPageRoute(
|
||||||
builder: (context) => ScriptEditPage(
|
builder: (context) => ScriptEditPage(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:qinglong_app/utils/sp_utils.dart';
|
|||||||
|
|
||||||
var themeProvider = ChangeNotifierProvider((ref) => ThemeViewModel());
|
var themeProvider = ChangeNotifierProvider((ref) => ThemeViewModel());
|
||||||
|
|
||||||
const commonColor = Color(0xFF299343);
|
Color commonColor = const Color(0xFF299343);
|
||||||
Color _primaryColor = commonColor;
|
Color _primaryColor = commonColor;
|
||||||
|
|
||||||
class ThemeViewModel extends ChangeNotifier {
|
class ThemeViewModel extends ChangeNotifier {
|
||||||
@@ -71,7 +71,10 @@ class ThemeViewModel extends ChangeNotifier {
|
|||||||
),
|
),
|
||||||
scaffoldBackgroundColor: const Color(0xfff5f5f5),
|
scaffoldBackgroundColor: const Color(0xfff5f5f5),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
labelStyle: TextStyle(color: _primaryColor),
|
labelStyle: TextStyle(
|
||||||
|
color: _primaryColor,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: _primaryColor,
|
color: _primaryColor,
|
||||||
@@ -152,7 +155,10 @@ class ThemeViewModel extends ChangeNotifier {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
labelStyle: TextStyle(color: _primaryColor),
|
labelStyle: TextStyle(
|
||||||
|
color: _primaryColor,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
focusedBorder: UnderlineInputBorder(
|
focusedBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: _primaryColor,
|
color: _primaryColor,
|
||||||
@@ -208,12 +214,15 @@ class ThemeViewModel extends ChangeNotifier {
|
|||||||
|
|
||||||
abstract class ThemeColors {
|
abstract class ThemeColors {
|
||||||
Color settingBgColor();
|
Color settingBgColor();
|
||||||
|
|
||||||
Color settingBordorColor();
|
Color settingBordorColor();
|
||||||
|
|
||||||
Color titleColor();
|
Color titleColor();
|
||||||
|
|
||||||
Color descColor();
|
Color descColor();
|
||||||
|
|
||||||
|
Color tabBarColor();
|
||||||
|
|
||||||
Color pinColor();
|
Color pinColor();
|
||||||
|
|
||||||
Color buttonBgColor();
|
Color buttonBgColor();
|
||||||
@@ -256,6 +265,11 @@ class LightThemeColors extends ThemeColors {
|
|||||||
Color settingBordorColor() {
|
Color settingBordorColor() {
|
||||||
return Colors.white;
|
return Colors.white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color tabBarColor() {
|
||||||
|
return const Color(0xffF7F7F7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DartThemeColors extends ThemeColors {
|
class DartThemeColors extends ThemeColors {
|
||||||
@@ -293,4 +307,9 @@ class DartThemeColors extends ThemeColors {
|
|||||||
Color settingBordorColor() {
|
Color settingBordorColor() {
|
||||||
return Color(0xff333333);
|
return Color(0xff333333);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color tabBarColor() {
|
||||||
|
return Colors.black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ class UserInfoViewModel {
|
|||||||
_useSecertLogined = SpUtil.getBool(spSecretLogined, defValue: false);
|
_useSecertLogined = SpUtil.getBool(spSecretLogined, defValue: false);
|
||||||
_host = SpUtil.getString(spHost, defValue: '');
|
_host = SpUtil.getString(spHost, defValue: '');
|
||||||
|
|
||||||
List<dynamic>? tempList =
|
List<dynamic>? tempList = jsonDecode(SpUtil.getString(spLoginHistory, defValue: '[]'));
|
||||||
jsonDecode(SpUtil.getString(spLoginHistory, defValue: '[]'));
|
|
||||||
|
|
||||||
if (tempList != null && tempList.isNotEmpty) {
|
if (tempList != null && tempList.isNotEmpty) {
|
||||||
for (Map<String, dynamic> value in tempList) {
|
for (Map<String, dynamic> value in tempList) {
|
||||||
@@ -41,8 +40,7 @@ class UserInfoViewModel {
|
|||||||
SpUtil.putString(spUserInfo, token);
|
SpUtil.putString(spUserInfo, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateUserName(
|
void updateUserName(String host, String userName, String password, bool secretLogin) {
|
||||||
String host, String userName, String password, bool secretLogin) {
|
|
||||||
updateHost(host);
|
updateHost(host);
|
||||||
_useSecretLogin(secretLogin);
|
_useSecretLogin(secretLogin);
|
||||||
_userName = userName;
|
_userName = userName;
|
||||||
@@ -95,13 +93,11 @@ class UserInfoViewModel {
|
|||||||
|
|
||||||
historyAccounts.removeWhere((element) => element.host == _host);
|
historyAccounts.removeWhere((element) => element.host == _host);
|
||||||
|
|
||||||
historyAccounts.insert(
|
historyAccounts.insert(0, UserInfoBean(userName: _userName, password: _passWord, useSecretLogined: _useSecertLogined, host: _host));
|
||||||
0,
|
|
||||||
UserInfoBean(
|
while (historyAccounts.length > 3) {
|
||||||
userName: _userName,
|
historyAccounts.removeLast();
|
||||||
password: _passWord,
|
}
|
||||||
useSecretLogined: _useSecertLogined,
|
|
||||||
host: _host));
|
|
||||||
|
|
||||||
SpUtil.putString(spLoginHistory, jsonEncode(historyAccounts));
|
SpUtil.putString(spLoginHistory, jsonEncode(historyAccounts));
|
||||||
}
|
}
|
||||||
@@ -121,8 +117,7 @@ class UserInfoBean {
|
|||||||
bool useSecretLogined = false;
|
bool useSecretLogined = false;
|
||||||
String? host;
|
String? host;
|
||||||
|
|
||||||
UserInfoBean(
|
UserInfoBean({this.userName, this.password, this.useSecretLogined = false, this.host});
|
||||||
{this.userName, this.password, this.useSecretLogined = false, this.host});
|
|
||||||
|
|
||||||
UserInfoBean.fromJson(Map<String, dynamic> json) {
|
UserInfoBean.fromJson(Map<String, dynamic> json) {
|
||||||
userName = json['userName'];
|
userName = json['userName'];
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ void main() async {
|
|||||||
await SpUtil.getInstance();
|
await SpUtil.getInstance();
|
||||||
getIt.registerSingleton<UserInfoViewModel>(UserInfoViewModel());
|
getIt.registerSingleton<UserInfoViewModel>(UserInfoViewModel());
|
||||||
|
|
||||||
|
await SystemChrome.setPreferredOrientations(
|
||||||
|
[
|
||||||
|
DeviceOrientation.portraitUp,
|
||||||
|
DeviceOrientation.portraitDown,
|
||||||
|
],
|
||||||
|
);
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
overrides: [
|
overrides: [
|
||||||
|
|||||||
2
lib/module/env/add_env_page.dart
vendored
@@ -187,7 +187,7 @@ class _AddEnvPageState extends ConsumerState<AddEnvPage> {
|
|||||||
envBean.remarks = _remarkController.text;
|
envBean.remarks = _remarkController.text;
|
||||||
HttpResponse<NullResponse> response = await Api.addEnv(
|
HttpResponse<NullResponse> response = await Api.addEnv(
|
||||||
_nameController.text, _valueController.text, _remarkController.text,
|
_nameController.text, _valueController.text, _remarkController.text,
|
||||||
id: envBean.sId);
|
id: envBean.id,nId: envBean.nId,);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
(envBean.sId == null) ? "新增成功" : "修改成功".toast();
|
(envBean.sId == null) ? "新增成功" : "修改成功".toast();
|
||||||
|
|||||||
6
lib/module/env/env_bean.dart
vendored
@@ -4,6 +4,8 @@ import 'package:json_conversion_annotation/json_conversion_annotation.dart';
|
|||||||
class EnvBean {
|
class EnvBean {
|
||||||
String? value;
|
String? value;
|
||||||
String? sId;
|
String? sId;
|
||||||
|
String? _id;
|
||||||
|
int? id;
|
||||||
int? created;
|
int? created;
|
||||||
int? status;
|
int? status;
|
||||||
String? timestamp;
|
String? timestamp;
|
||||||
@@ -12,8 +14,12 @@ class EnvBean {
|
|||||||
|
|
||||||
EnvBean({this.value, this.sId, this.created, this.status, this.timestamp, this.name, this.remarks});
|
EnvBean({this.value, this.sId, this.created, this.status, this.timestamp, this.name, this.remarks});
|
||||||
|
|
||||||
|
get nId => _id;
|
||||||
|
|
||||||
EnvBean.fromJson(Map<String, dynamic> json) {
|
EnvBean.fromJson(Map<String, dynamic> json) {
|
||||||
value = json['value'];
|
value = json['value'];
|
||||||
|
id = json['id'];
|
||||||
|
_id = json['_id'];
|
||||||
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
||||||
created = int.tryParse(json['created'].toString());
|
created = int.tryParse(json['created'].toString());
|
||||||
status = json['status'];
|
status = json['status'];
|
||||||
|
|||||||
347
lib/module/env/env_page.dart
vendored
@@ -23,6 +23,14 @@ class EnvPage extends StatefulWidget {
|
|||||||
class _EnvPageState extends State<EnvPage> {
|
class _EnvPageState extends State<EnvPage> {
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_searchController.addListener(() {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseStateWidget<EnvViewModel>(
|
return BaseStateWidget<EnvViewModel>(
|
||||||
@@ -37,7 +45,7 @@ class _EnvPageState extends State<EnvPage> {
|
|||||||
(value.remarks?.contains(_searchController.text) ?? false)) {
|
(value.remarks?.contains(_searchController.text) ?? false)) {
|
||||||
list.add(EnvItemCell(
|
list.add(EnvItemCell(
|
||||||
value,
|
value,
|
||||||
i + 1,
|
i,
|
||||||
ref,
|
ref,
|
||||||
key: ValueKey(value.sId),
|
key: ValueKey(value.sId),
|
||||||
));
|
));
|
||||||
@@ -51,26 +59,28 @@ class _EnvPageState extends State<EnvPage> {
|
|||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return model.loadData(false);
|
return model.loadData(false);
|
||||||
},
|
},
|
||||||
child: ReorderableListView(
|
child: SlidableAutoCloseBehavior(
|
||||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
child: ReorderableListView(
|
||||||
header: searchCell(ref),
|
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||||
onReorder: (int oldIndex, int newIndex) {
|
header: searchCell(ref),
|
||||||
if (list.length != model.list.length) {
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
"请先清空搜索关键词".toast();
|
if (list.length != model.list.length) {
|
||||||
return;
|
"请先清空搜索关键词".toast();
|
||||||
}
|
return;
|
||||||
|
|
||||||
setState(() {
|
|
||||||
//交换数据
|
|
||||||
if (newIndex > oldIndex) {
|
|
||||||
newIndex -= 1;
|
|
||||||
}
|
}
|
||||||
final EnvBean item = model.list.removeAt(oldIndex);
|
|
||||||
model.list.insert(newIndex, item);
|
setState(() {
|
||||||
model.update(item.sId ?? "", newIndex, oldIndex);
|
//交换数据
|
||||||
});
|
if (newIndex > oldIndex) {
|
||||||
},
|
newIndex -= 1;
|
||||||
children: list,
|
}
|
||||||
|
final EnvBean item = model.list.removeAt(oldIndex);
|
||||||
|
model.list.insert(newIndex, item);
|
||||||
|
model.update(item.sId ?? "", newIndex, oldIndex);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
children: list,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -133,185 +143,181 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return ColoredBox(
|
||||||
onTap: () {
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
Navigator.of(context).pushNamed(Routes.routeEnvDetail, arguments: bean);
|
child: Slidable(
|
||||||
},
|
key: ValueKey(bean.sId),
|
||||||
child: ColoredBox(
|
endActionPane: ActionPane(
|
||||||
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
motion: const StretchMotion(),
|
||||||
child: Slidable(
|
extentRatio: 0.5,
|
||||||
key: ValueKey(bean.sId),
|
children: [
|
||||||
endActionPane: ActionPane(
|
SlidableAction(
|
||||||
motion: const ScrollMotion(),
|
backgroundColor: const Color(0xff5D5E70),
|
||||||
extentRatio: 0.45,
|
onPressed: (_) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean);
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.pencil_outline,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffA356D6),
|
||||||
|
onPressed: (_) {
|
||||||
|
enableEnv(context);
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffEA4D3E),
|
||||||
|
onPressed: (_) {
|
||||||
|
delEnv(context, ref);
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.delete,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SlidableAction(
|
Material(
|
||||||
backgroundColor: Colors.grey,
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
flex: 1,
|
child: InkWell(
|
||||||
onPressed: (_) {
|
onTap: () {
|
||||||
Navigator.of(context).pushNamed(Routes.routeAddEnv, arguments: bean);
|
Navigator.of(context).pushNamed(Routes.routeEnvDetail, arguments: bean);
|
||||||
},
|
},
|
||||||
foregroundColor: Colors.white,
|
child: Container(
|
||||||
icon: CupertinoIcons.pencil_outline,
|
padding: const EdgeInsets.symmetric(
|
||||||
),
|
horizontal: 15,
|
||||||
SlidableAction(
|
vertical: 8,
|
||||||
backgroundColor: Colors.orange,
|
),
|
||||||
flex: 1,
|
child: Column(
|
||||||
onPressed: (_) {
|
mainAxisSize: MainAxisSize.min,
|
||||||
enableEnv();
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
},
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
foregroundColor: Colors.white,
|
children: [
|
||||||
icon: bean.status == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
SlidableAction(
|
children: [
|
||||||
backgroundColor: Colors.red,
|
Expanded(
|
||||||
flex: 1,
|
child: Row(
|
||||||
onPressed: (_) {
|
children: [
|
||||||
delEnv(context, ref);
|
bean.status == 1
|
||||||
},
|
? const Icon(
|
||||||
foregroundColor: Colors.white,
|
Icons.dnd_forwardslash,
|
||||||
icon: CupertinoIcons.delete,
|
size: 18,
|
||||||
),
|
color: Color(0xffEA4D3E),
|
||||||
],
|
)
|
||||||
),
|
: Container(
|
||||||
child: SizedBox(
|
padding: const EdgeInsets.symmetric(
|
||||||
width: MediaQuery.of(context).size.width,
|
horizontal: 5,
|
||||||
child: Column(
|
),
|
||||||
mainAxisSize: MainAxisSize.min,
|
decoration: BoxDecoration(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
borderRadius: BorderRadius.circular(5),
|
||||||
children: [
|
border: Border.all(color: ref.watch(themeProvider).primaryColor, width: 1),
|
||||||
Container(
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
child: Text(
|
||||||
horizontal: 15,
|
"${getIndexByIndex(context, index)}",
|
||||||
vertical: 8,
|
style: TextStyle(color: ref.watch(themeProvider).primaryColor, fontSize: 12),
|
||||||
),
|
),
|
||||||
child: Column(
|
),
|
||||||
mainAxisSize: MainAxisSize.min,
|
const SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
width: 5,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
),
|
||||||
children: [
|
Material(
|
||||||
Row(
|
color: Colors.transparent,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: Text(
|
||||||
children: [
|
bean.name ?? "",
|
||||||
Expanded(
|
maxLines: 1,
|
||||||
child: Row(
|
style: TextStyle(
|
||||||
children: [
|
overflow: TextOverflow.ellipsis,
|
||||||
Material(
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
color: Colors.transparent,
|
fontSize: 16,
|
||||||
child: Text(
|
),
|
||||||
bean.name ?? "",
|
|
||||||
maxLines: 1,
|
|
||||||
style: TextStyle(
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
],
|
width: 5,
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
const SizedBox(
|
child: Visibility(
|
||||||
width: 5,
|
visible: bean.remarks != null && bean.remarks!.isNotEmpty,
|
||||||
),
|
child: Material(
|
||||||
Material(
|
color: Colors.transparent,
|
||||||
color: Colors.transparent,
|
child: Text(
|
||||||
child: Text(
|
"(${bean.remarks})",
|
||||||
Utils.formatGMTTime(bean.timestamp ?? ""),
|
maxLines: 1,
|
||||||
maxLines: 1,
|
style: TextStyle(
|
||||||
style: TextStyle(
|
height: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
],
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 5,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(color: ref.watch(themeProvider).primaryColor, width: 1),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"$index",
|
|
||||||
style: TextStyle(color: ref.watch(themeProvider).primaryColor, fontSize: 12),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 5,
|
width: 15,
|
||||||
),
|
|
||||||
bean.status == 1
|
|
||||||
? const Icon(
|
|
||||||
Icons.dnd_forwardslash,
|
|
||||||
size: 12,
|
|
||||||
color: Colors.red,
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
|
|
||||||
const SizedBox(
|
|
||||||
width: 5,
|
|
||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: Text(
|
child: Text(
|
||||||
bean.remarks ?? "-",
|
Utils.formatGMTTime(bean.timestamp ?? ""),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
height: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
const SizedBox(
|
height: 15,
|
||||||
height: 8,
|
),
|
||||||
),
|
Material(
|
||||||
Material(
|
color: Colors.transparent,
|
||||||
color: Colors.transparent,
|
child: Text(
|
||||||
child: Text(
|
bean.value ?? "",
|
||||||
bean.value ?? "",
|
maxLines: 1,
|
||||||
maxLines: 1,
|
style: TextStyle(
|
||||||
style: TextStyle(
|
overflow: TextOverflow.ellipsis,
|
||||||
overflow: TextOverflow.ellipsis,
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
fontSize: 12,
|
||||||
fontSize: 12,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(
|
),
|
||||||
height: 1,
|
const Divider(
|
||||||
indent: 15,
|
height: 1,
|
||||||
),
|
indent: 15,
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableEnv() {
|
void enableEnv(BuildContext context) {
|
||||||
ref.read(envProvider).enableEnv(bean.sId!, bean.status!);
|
ref.read(envProvider).enableEnv(bean.sId!, bean.status!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delEnv(BuildContext context, WidgetRef ref) {
|
void delEnv(BuildContext context, WidgetRef ref) {
|
||||||
showCupertinoDialog(
|
showCupertinoDialog(
|
||||||
|
useRootNavigator: false,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CupertinoAlertDialog(
|
builder: (context) => CupertinoAlertDialog(
|
||||||
title: const Text("确认删除"),
|
title: const Text("确认删除"),
|
||||||
@@ -344,4 +350,17 @@ class EnvItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getIndexByIndex(BuildContext context, int index) {
|
||||||
|
var list = ref.watch(envProvider.notifier).list;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i <= index; i++) {
|
||||||
|
if (list.length > index && list[i].status == 0) {
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,9 @@ import 'package:qinglong_app/base/ql_app_bar.dart';
|
|||||||
import 'package:qinglong_app/base/routes.dart';
|
import 'package:qinglong_app/base/routes.dart';
|
||||||
import 'package:qinglong_app/module/config/config_page.dart';
|
import 'package:qinglong_app/module/config/config_page.dart';
|
||||||
import 'package:qinglong_app/module/env/env_page.dart';
|
import 'package:qinglong_app/module/env/env_page.dart';
|
||||||
import 'package:qinglong_app/module/home/system_bean.dart';
|
|
||||||
import 'package:qinglong_app/module/others/other_page.dart';
|
import 'package:qinglong_app/module/others/other_page.dart';
|
||||||
import 'package:qinglong_app/module/task/task_page.dart';
|
import 'package:qinglong_app/module/task/task_page.dart';
|
||||||
import 'package:move_to_background/move_to_background.dart';
|
import 'package:move_to_background/move_to_background.dart';
|
||||||
import 'package:qinglong_app/utils/update_utils.dart';
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import '../../utils/utils.dart';
|
import '../../utils/utils.dart';
|
||||||
@@ -47,7 +45,6 @@ class _HomePageState extends ConsumerState<HomePage>
|
|||||||
_title = titles[0].title;
|
_title = titles[0].title;
|
||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
update();
|
|
||||||
getSystemBean();
|
getSystemBean();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -243,17 +240,6 @@ class _HomePageState extends ConsumerState<HomePage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() async {
|
|
||||||
String? result = await UpdateUtils().checkUpdate();
|
|
||||||
if (result != null && result.isNotEmpty) {
|
|
||||||
UpdateDialog updateDialog = UpdateDialog(context,
|
|
||||||
title: "发现新版本", updateContent: "版本号:v$result", onUpdate: () {
|
|
||||||
UpdateUtils.launchURL(result);
|
|
||||||
});
|
|
||||||
updateDialog.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void isNewYearDuration() {
|
void isNewYearDuration() {
|
||||||
DateTime date = DateTime.now();
|
DateTime date = DateTime.now();
|
||||||
DateTime dateYear1 = DateTime(2022, 1, 29);
|
DateTime dateYear1 = DateTime(2022, 1, 29);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/// @author NewTab
|
||||||
|
|
||||||
import 'package:json_conversion_annotation/json_conversion_annotation.dart';
|
import 'package:json_conversion_annotation/json_conversion_annotation.dart';
|
||||||
|
|
||||||
@@ -11,6 +12,98 @@ class SystemBean {
|
|||||||
version = json['version'];
|
version = json['version'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//2.12.2 以及以上版本,日志从dirs换成了data
|
||||||
|
bool isUpperVersion2_12_2() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) >= 021202) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.13.0 以及以上版本日志详情接口参数有变化
|
||||||
|
bool isUpperVersion2_13_0() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) >= 021300) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.10.13以上版本,针对任务,环境变量编辑做了修改
|
||||||
|
bool isUpperVersion() {
|
||||||
|
try {
|
||||||
|
List<String>? version1 = version?.split("\.");
|
||||||
|
|
||||||
|
String f = version1?[0] ?? "2";
|
||||||
|
String s = version1?[1] ?? "10";
|
||||||
|
String t = version1?[2] ?? "0";
|
||||||
|
|
||||||
|
if (f.length == 1) {
|
||||||
|
f = "0$f";
|
||||||
|
}
|
||||||
|
if (s.length == 1) {
|
||||||
|
s = "0$s";
|
||||||
|
}
|
||||||
|
if (t.length == 1) {
|
||||||
|
t = "0$t";
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempSum = "$f$s$t";
|
||||||
|
|
||||||
|
if ((int.tryParse(tempSum) ?? 1) > 021013) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
data['version'] = this.version;
|
data['version'] = this.version;
|
||||||
@@ -20,4 +113,4 @@ class SystemBean {
|
|||||||
static SystemBean jsonConversion(Map<String, dynamic> json) {
|
static SystemBean jsonConversion(Map<String, dynamic> json) {
|
||||||
return SystemBean.fromJson(json);
|
return SystemBean.fromJson(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:qinglong_app/base/http/api.dart';
|
|
||||||
import 'package:qinglong_app/base/http/http.dart';
|
import 'package:qinglong_app/base/http/http.dart';
|
||||||
import 'package:qinglong_app/base/routes.dart';
|
import 'package:qinglong_app/base/routes.dart';
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
import 'package:qinglong_app/base/theme.dart';
|
||||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
||||||
import 'package:qinglong_app/main.dart';
|
import 'package:qinglong_app/main.dart';
|
||||||
import 'package:qinglong_app/module/login/user_bean.dart';
|
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
import 'package:qinglong_app/utils/extension.dart';
|
||||||
import 'package:qinglong_app/utils/login_helper.dart';
|
import 'package:qinglong_app/utils/login_helper.dart';
|
||||||
import 'package:qinglong_app/utils/update_utils.dart';
|
|
||||||
import 'package:qinglong_app/utils/utils.dart';
|
import 'package:qinglong_app/utils/utils.dart';
|
||||||
import 'package:flip_card/flip_card.dart';
|
import 'package:flip_card/flip_card.dart';
|
||||||
|
|
||||||
@@ -66,7 +63,6 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
}
|
}
|
||||||
getIt<UserInfoViewModel>().updateToken("");
|
getIt<UserInfoViewModel>().updateToken("");
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
update();
|
|
||||||
if (useSecretLogin) {
|
if (useSecretLogin) {
|
||||||
cardKey.currentState?.toggleCard();
|
cardKey.currentState?.toggleCard();
|
||||||
}
|
}
|
||||||
@@ -129,15 +125,9 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
}
|
}
|
||||||
WidgetsBinding.instance?.endOfFrame;
|
WidgetsBinding.instance?.endOfFrame;
|
||||||
},
|
},
|
||||||
child: ColorFiltered(
|
child: Image.asset(
|
||||||
colorFilter: ColorFilter.mode(
|
"assets/images/ql.png",
|
||||||
ref.watch(themeProvider).primaryColor,
|
height: 45,
|
||||||
BlendMode.srcIn,
|
|
||||||
),
|
|
||||||
child: Image.asset(
|
|
||||||
"assets/images/ql.png",
|
|
||||||
height: 45,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -522,16 +512,6 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() async {
|
|
||||||
String? result = await UpdateUtils().checkUpdate();
|
|
||||||
if (result != null && result.isNotEmpty) {
|
|
||||||
UpdateDialog updateDialog = UpdateDialog(context, title: "发现新版本", updateContent: "版本号:v${result}", onUpdate: () {
|
|
||||||
UpdateUtils.launchURL(result);
|
|
||||||
});
|
|
||||||
updateDialog.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildCell(UserInfoBean bean) {
|
Widget buildCell(UserInfoBean bean) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:qinglong_app/base/ql_app_bar.dart';
|
import 'package:qinglong_app/base/ql_app_bar.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
import 'package:qinglong_app/base/theme.dart';
|
||||||
import 'package:qinglong_app/utils/update_utils.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
@@ -25,19 +24,6 @@ class _AboutPageState extends ConsumerState<AboutPage> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
getInfo();
|
getInfo();
|
||||||
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() async {
|
|
||||||
String? result = await UpdateUtils().checkUpdate(true);
|
|
||||||
if (result != null && result.isNotEmpty) {
|
|
||||||
UpdateDialog updateDialog = UpdateDialog(context, title: "发现新版本", updateContent: "版本号:v${result}", onUpdate: () {
|
|
||||||
UpdateUtils.launchURL(result);
|
|
||||||
});
|
|
||||||
updateDialog.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,316 +0,0 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:flutter_slidable/flutter_slidable.dart';
|
|
||||||
import 'package:qinglong_app/base/http/api.dart';
|
|
||||||
import 'package:qinglong_app/base/http/http.dart';
|
|
||||||
import 'package:qinglong_app/base/ql_app_bar.dart';
|
|
||||||
import 'package:qinglong_app/base/routes.dart';
|
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
|
||||||
import 'package:qinglong_app/base/userinfo_viewmodel.dart';
|
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
|
||||||
import 'package:qinglong_app/utils/login_helper.dart';
|
|
||||||
|
|
||||||
import '../../main.dart';
|
|
||||||
|
|
||||||
class ChangeAccountPage extends ConsumerStatefulWidget {
|
|
||||||
const ChangeAccountPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_ChangeAccountPageState createState() => _ChangeAccountPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ChangeAccountPageState extends ConsumerState<ChangeAccountPage> {
|
|
||||||
String isLoginingHost = "";
|
|
||||||
String preHost = "";
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
preHost = getIt<UserInfoViewModel>().historyAccounts.first.host ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: QlAppBar(
|
|
||||||
canBack: true,
|
|
||||||
title: "切换账号",
|
|
||||||
),
|
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: MediaQuery.of(context).size.height / 10,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"轻触账号以切换登录",
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
|
||||||
fontSize: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 30,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 15,
|
|
||||||
),
|
|
||||||
child: ListView.separated(
|
|
||||||
shrinkWrap: true,
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (index == getIt<UserInfoViewModel>().historyAccounts.length) {
|
|
||||||
return addAccount();
|
|
||||||
}
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
child: Container(
|
|
||||||
color: ref.watch(themeProvider).themeColor.settingBordorColor(),
|
|
||||||
child: buildCell(index),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
separatorBuilder: (_, __) {
|
|
||||||
return const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
itemCount: getIt<UserInfoViewModel>().historyAccounts.length + 1),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildCell(int index) {
|
|
||||||
Widget child = ListTile(
|
|
||||||
title: Text(
|
|
||||||
getIt<UserInfoViewModel>().historyAccounts[index].host ?? "",
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 15,
|
|
||||||
),
|
|
||||||
minVerticalPadding: 10,
|
|
||||||
subtitle: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 10.0),
|
|
||||||
child: Text(
|
|
||||||
getIt<UserInfoViewModel>().historyAccounts[index].userName ?? "",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: index == 0
|
|
||||||
? Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 5,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(color: ref.watch(themeProvider).primaryColor, width: 1),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"已登录",
|
|
||||||
style: TextStyle(color: ref.watch(themeProvider).primaryColor, fontSize: 12),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: (isLoginingHost.isNotEmpty
|
|
||||||
? SizedBox(
|
|
||||||
width: 15,
|
|
||||||
height: 15,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: ref.watch(themeProvider).primaryColor,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink()),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (getIt<UserInfoViewModel>().historyAccounts[index].host == getIt<UserInfoViewModel>().host) {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Slidable(
|
|
||||||
key: ValueKey(index),
|
|
||||||
endActionPane: ActionPane(
|
|
||||||
motion: const ScrollMotion(),
|
|
||||||
extentRatio: 0.15,
|
|
||||||
children: [
|
|
||||||
SlidableAction(
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
flex: 1,
|
|
||||||
onPressed: (_) {
|
|
||||||
getIt<UserInfoViewModel>().removeHistoryAccount(getIt<UserInfoViewModel>().historyAccounts[index].host);
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
icon: CupertinoIcons.delete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () {
|
|
||||||
loginNewByBean(getIt<UserInfoViewModel>().historyAccounts[index]);
|
|
||||||
},
|
|
||||||
child: child),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoginHelper? helper;
|
|
||||||
|
|
||||||
void loginNewByBean(UserInfoBean historyAccount) async {
|
|
||||||
isLoginingHost = historyAccount.host ?? "";
|
|
||||||
setState(() {});
|
|
||||||
helper = LoginHelper(
|
|
||||||
historyAccount.useSecretLogined,
|
|
||||||
historyAccount.host ?? "",
|
|
||||||
historyAccount.userName ?? "",
|
|
||||||
historyAccount.password ?? "",
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
var response = await helper!.login();
|
|
||||||
dealLoginResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dealLoginResponse(int response) {
|
|
||||||
if (response == LoginHelper.success) {
|
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil(Routes.routeHomePage, (_) => false);
|
|
||||||
} else if (response == LoginHelper.failed) {
|
|
||||||
loginFailed();
|
|
||||||
} else {
|
|
||||||
twoFact();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void loginFailed() {
|
|
||||||
isLoginingHost = "";
|
|
||||||
Http.clear();
|
|
||||||
getIt<UserInfoViewModel>().updateHost(preHost);
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void twoFact() {
|
|
||||||
String twoFact = "";
|
|
||||||
showCupertinoDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => CupertinoAlertDialog(
|
|
||||||
title: const Text("两步验证"),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: TextField(
|
|
||||||
onChanged: (value) {
|
|
||||||
twoFact = value;
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
|
||||||
hintText: "请输入code",
|
|
||||||
),
|
|
||||||
autofocus: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child: const Text(
|
|
||||||
"取消",
|
|
||||||
style: TextStyle(
|
|
||||||
color: Color(0xff999999),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child: Text(
|
|
||||||
"确定",
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.watch(themeProvider).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
Navigator.of(context).pop(true);
|
|
||||||
if (helper != null) {
|
|
||||||
var response = await helper!.loginTwice(twoFact);
|
|
||||||
dealLoginResponse(response);
|
|
||||||
} else {
|
|
||||||
"状态异常".toast();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)).then((value) {
|
|
||||||
if (value == null) {
|
|
||||||
isLoginingHost = "";
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget addAccount() {
|
|
||||||
return GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
|
||||||
Routes.routeLogin,
|
|
||||||
(_) => false,
|
|
||||||
arguments: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 15,
|
|
||||||
horizontal: 15,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: ref.watch(themeProvider).themeColor.settingBordorColor(),
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(
|
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Icon(
|
|
||||||
CupertinoIcons.add,
|
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 15,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"添加账号",
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -304,41 +304,6 @@ class _OtherPageState extends ConsumerState<OtherPage> {
|
|||||||
const Divider(
|
const Divider(
|
||||||
indent: 15,
|
indent: 15,
|
||||||
),
|
),
|
||||||
GestureDetector(
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamed(Routes.routeChangeAccount);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 15,
|
|
||||||
right: 15,
|
|
||||||
top: 5,
|
|
||||||
bottom: 5,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"切换账号",
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
const Icon(
|
|
||||||
CupertinoIcons.right_chevron,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
indent: 15,
|
|
||||||
),
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import 'package:code_text_field/code_text_field.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:highlight/languages/javascript.dart';
|
import 'package:highlight/languages/javascript.dart';
|
||||||
|
import 'package:highlight/languages/json.dart';
|
||||||
|
import 'package:highlight/languages/powershell.dart';
|
||||||
|
import 'package:highlight/languages/python.dart';
|
||||||
|
import 'package:highlight/languages/vbscript-html.dart';
|
||||||
|
import 'package:highlight/languages/yaml.dart';
|
||||||
import 'package:qinglong_app/base/http/api.dart';
|
import 'package:qinglong_app/base/http/api.dart';
|
||||||
import 'package:qinglong_app/base/http/http.dart';
|
import 'package:qinglong_app/base/http/http.dart';
|
||||||
import 'package:qinglong_app/base/ql_app_bar.dart';
|
import 'package:qinglong_app/base/ql_app_bar.dart';
|
||||||
@@ -41,11 +46,32 @@ class _ScriptEditPageState extends ConsumerState<ScriptEditPage> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLanguageType(String title) {
|
||||||
|
if (title.endsWith(".js")) {
|
||||||
|
return javascript;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.endsWith(".sh")) {
|
||||||
|
return powershell;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.endsWith(".py")) {
|
||||||
|
return python;
|
||||||
|
}
|
||||||
|
if (title.endsWith(".json")) {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
if (title.endsWith(".yaml")) {
|
||||||
|
return yaml;
|
||||||
|
}
|
||||||
|
return vbscriptHtml;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_codeController ??= CodeController(
|
_codeController ??= CodeController(
|
||||||
text: widget.content,
|
text: widget.content,
|
||||||
language: javascript,
|
language: getLanguageType(widget.title),
|
||||||
onChange: (value) {
|
onChange: (value) {
|
||||||
result = value;
|
result = value;
|
||||||
},
|
},
|
||||||
@@ -91,10 +117,24 @@ class _ScriptEditPageState extends ConsumerState<ScriptEditPage> {
|
|||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
child: CodeField(
|
child: Padding(
|
||||||
controller: _codeController!,
|
padding: const EdgeInsets.symmetric(
|
||||||
expands: true,
|
horizontal: 10,
|
||||||
background: ref.watch(themeProvider).themeColor.settingBgColor(),
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: CodeField(
|
||||||
|
controller: _codeController!,
|
||||||
|
expands: true,
|
||||||
|
wrap: true,
|
||||||
|
lineNumberStyle: LineNumberStyle(
|
||||||
|
width: 0,
|
||||||
|
margin: 0,
|
||||||
|
textStyle: TextStyle(
|
||||||
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background: ref.watch(themeProvider).themeColor.tabBarColor(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,6 +20,18 @@ class ScriptPage extends ConsumerStatefulWidget {
|
|||||||
|
|
||||||
class _ScriptPageState extends ConsumerState<ScriptPage> with LazyLoadState<ScriptPage> {
|
class _ScriptPageState extends ConsumerState<ScriptPage> with LazyLoadState<ScriptPage> {
|
||||||
List<ScriptBean> list = [];
|
List<ScriptBean> list = [];
|
||||||
|
final TextEditingController _searchController = TextEditingController();
|
||||||
|
|
||||||
|
final TextEditingController _nameController = TextEditingController();
|
||||||
|
String? path;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_searchController.addListener(() {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -30,83 +42,167 @@ class _ScriptPageState extends ConsumerState<ScriptPage> with LazyLoadState<Scri
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
title: "脚本管理",
|
title: "脚本管理",
|
||||||
|
actions: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
addScript();
|
||||||
|
},
|
||||||
|
child: const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 15,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
CupertinoIcons.add,
|
||||||
|
size: 24,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: list.isEmpty
|
body: list.isEmpty
|
||||||
? const Center(
|
? const Center(
|
||||||
child: CupertinoActivityIndicator(),
|
child: CupertinoActivityIndicator(),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
ScriptBean item = list[index];
|
if (index == 0) {
|
||||||
|
return searchCell(ref);
|
||||||
|
}
|
||||||
|
|
||||||
return ColoredBox(
|
ScriptBean item = list[index - 1];
|
||||||
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
|
||||||
child: (item.children != null && item.children!.isNotEmpty)
|
if (_searchController.text.isEmpty ||
|
||||||
? ExpansionTile(
|
(item.title?.contains(_searchController.text) ?? false) ||
|
||||||
title: Text(
|
(item.value?.contains(_searchController.text) ?? false) ||
|
||||||
item.title ?? "",
|
((item.children?.where((e) {
|
||||||
style: TextStyle(
|
return (e.title?.contains(_searchController.text) ?? false) || (e.value?.contains(_searchController.text) ?? false);
|
||||||
color:
|
}).isNotEmpty ??
|
||||||
(item.disabled ?? false) ? ref.watch(themeProvider).themeColor.descColor() : ref.watch(themeProvider).themeColor.titleColor(),
|
false))) {
|
||||||
fontSize: 16,
|
return ColoredBox(
|
||||||
),
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
),
|
child: (item.children != null && item.children!.isNotEmpty)
|
||||||
children: item.children!
|
? ExpansionTile(
|
||||||
.map((e) => ListTile(
|
title: Text(
|
||||||
onTap: () {
|
item.title ?? "",
|
||||||
Navigator.of(context).pushNamed(
|
style: TextStyle(
|
||||||
Routes.routeScriptDetail,
|
color: (item.disabled ?? false)
|
||||||
arguments: {
|
? ref.watch(themeProvider).themeColor.descColor()
|
||||||
"title": e.title,
|
: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
"path": e.parent,
|
fontSize: 16,
|
||||||
},
|
),
|
||||||
).then((value) {
|
),
|
||||||
if (value != null && value == true) {
|
children: item.children!
|
||||||
loadData();
|
.where((element) {
|
||||||
}
|
if (_searchController.text.isEmpty) {
|
||||||
});
|
return true;
|
||||||
},
|
}
|
||||||
title: Text(
|
return (element.title?.contains(_searchController.text) ?? false) ||
|
||||||
e.title ?? "",
|
(element.value?.contains(_searchController.text) ?? false);
|
||||||
style: TextStyle(
|
})
|
||||||
color: (item.disabled ?? false)
|
.map((e) => ListTile(
|
||||||
? ref.watch(themeProvider).themeColor.descColor()
|
onTap: () {
|
||||||
: ref.watch(themeProvider).themeColor.titleColor(),
|
Navigator.of(context).pushNamed(
|
||||||
fontSize: 14,
|
Routes.routeScriptDetail,
|
||||||
),
|
arguments: {
|
||||||
),
|
"title": e.title,
|
||||||
))
|
"path": e.parent,
|
||||||
.toList(),
|
},
|
||||||
)
|
).then((value) {
|
||||||
: ListTile(
|
if (value != null && value == true) {
|
||||||
onTap: () {
|
loadData();
|
||||||
Navigator.of(context).pushNamed(
|
}
|
||||||
Routes.routeScriptDetail,
|
});
|
||||||
arguments: {
|
},
|
||||||
"title": item.title,
|
title: Text(
|
||||||
"path": "",
|
e.title ?? "",
|
||||||
},
|
style: TextStyle(
|
||||||
).then(
|
color: (item.disabled ?? false)
|
||||||
(value) {
|
? ref.watch(themeProvider).themeColor.descColor()
|
||||||
if (value != null && value == true) {
|
: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
loadData();
|
fontSize: 14,
|
||||||
}
|
),
|
||||||
},
|
),
|
||||||
);
|
))
|
||||||
},
|
.toList(),
|
||||||
title: Text(
|
)
|
||||||
item.title ?? "",
|
: ListTile(
|
||||||
style: TextStyle(
|
onTap: () {
|
||||||
color:
|
Navigator.of(context).pushNamed(
|
||||||
(item.disabled ?? false) ? ref.watch(themeProvider).themeColor.descColor() : ref.watch(themeProvider).themeColor.titleColor(),
|
Routes.routeScriptDetail,
|
||||||
fontSize: 16,
|
arguments: {
|
||||||
),
|
"title": item.title,
|
||||||
),
|
"path": "",
|
||||||
),
|
},
|
||||||
);
|
).then(
|
||||||
},
|
(value) {
|
||||||
itemCount: list.length,
|
if (value != null && value == true) {
|
||||||
),
|
loadData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
item.title ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
color: (item.disabled ?? false)
|
||||||
|
? ref.watch(themeProvider).themeColor.descColor()
|
||||||
|
: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemCount: list.length + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget searchCell(WidgetRef context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 15,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: CupertinoSearchTextField(
|
||||||
|
onSubmitted: (value) {
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
onSuffixTap: () {
|
||||||
|
_searchController.text = "";
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
controller: _searchController,
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
30,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 5,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
suffixInsets: const EdgeInsets.only(
|
||||||
|
right: 15,
|
||||||
|
),
|
||||||
|
prefixInsets: const EdgeInsets.only(
|
||||||
|
top: 6,
|
||||||
|
bottom: 6,
|
||||||
|
left: 15,
|
||||||
|
),
|
||||||
|
placeholderStyle: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: context.watch(themeProvider).themeColor.descColor(),
|
||||||
|
),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
placeholder: "搜索",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,4 +225,139 @@ class _ScriptPageState extends ConsumerState<ScriptPage> with LazyLoadState<Scri
|
|||||||
void onLazyLoad() {
|
void onLazyLoad() {
|
||||||
loadData();
|
loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String scriptPath = "";
|
||||||
|
|
||||||
|
void addScript() {
|
||||||
|
showCupertinoDialog(
|
||||||
|
useRootNavigator: false,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => CupertinoAlertDialog(
|
||||||
|
title: const Text("新增脚本"),
|
||||||
|
content: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"脚本名称:",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
isDense: true,
|
||||||
|
contentPadding: EdgeInsets.all(4),
|
||||||
|
hintText: "请输入脚本名称",
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
autofocus: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"脚本所属文件夹:",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
DropdownButtonFormField<String>(
|
||||||
|
items: list
|
||||||
|
.where((element) => element.children?.isNotEmpty ?? false)
|
||||||
|
.map((e) => DropdownMenuItem(
|
||||||
|
value: e.value,
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2,
|
||||||
|
child: Text(
|
||||||
|
e.value ?? "",
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList()
|
||||||
|
..insert(
|
||||||
|
0,
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: "",
|
||||||
|
child: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2,
|
||||||
|
child: const Text(
|
||||||
|
"根目录",
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
value: scriptPath,
|
||||||
|
onChanged: (value) {
|
||||||
|
scriptPath = value ?? "";
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
CupertinoDialogAction(
|
||||||
|
child: const Text(
|
||||||
|
"取消",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xff999999),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CupertinoDialogAction(
|
||||||
|
child: Text(
|
||||||
|
"确定",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ref.watch(themeProvider).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
"提交中...".toast();
|
||||||
|
HttpResponse<NullResponse> response = await Api.addScript(
|
||||||
|
_nameController.text,
|
||||||
|
scriptPath,
|
||||||
|
"## created by 青龙客户端 ${DateTime.now()}\n\n",
|
||||||
|
);
|
||||||
|
if (response.success) {
|
||||||
|
"提交成功".toast();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
Routes.routeScriptUpdate,
|
||||||
|
arguments: {
|
||||||
|
"title": _nameController.text,
|
||||||
|
"path": scriptPath,
|
||||||
|
"content": "## created by 青龙客户端 ${DateTime.now()}\n\n",
|
||||||
|
},
|
||||||
|
).then((value) {
|
||||||
|
if (value != null && value == true) {
|
||||||
|
_nameController.text = "";
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
(response.message ?? "").toast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,20 +6,30 @@ class TaskLogBean {
|
|||||||
String? name;
|
String? name;
|
||||||
bool? isDir;
|
bool? isDir;
|
||||||
List<String>? files;
|
List<String>? files;
|
||||||
|
List<Children>? children;
|
||||||
|
|
||||||
TaskLogBean({this.name, this.isDir, this.files});
|
TaskLogBean({this.name, this.files});
|
||||||
|
|
||||||
TaskLogBean.fromJson(Map<String, dynamic> json) {
|
TaskLogBean.fromJson(Map<String, dynamic> json) {
|
||||||
name = json['name'];
|
name = json['name'] ?? json['title'];
|
||||||
isDir = json['isDir'];
|
isDir = json['isDir'] ?? (json['type'] == "directory");
|
||||||
files = json['files'].cast<String>();
|
|
||||||
|
files = json['files']?.cast<String>();
|
||||||
|
if (json['children'] != null) {
|
||||||
|
children = <Children>[];
|
||||||
|
json['children'].forEach((v) {
|
||||||
|
children!.add(Children.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
data['name'] = this.name;
|
data['name'] = this.name;
|
||||||
data['isDir'] = this.isDir;
|
|
||||||
data['files'] = this.files;
|
data['files'] = this.files;
|
||||||
|
if (this.children != null) {
|
||||||
|
data['children'] = this.children!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,3 +37,31 @@ class TaskLogBean {
|
|||||||
return TaskLogBean.fromJson(json);
|
return TaskLogBean.fromJson(json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Children {
|
||||||
|
String? title;
|
||||||
|
String? value;
|
||||||
|
String? type;
|
||||||
|
String? key;
|
||||||
|
String? parent;
|
||||||
|
|
||||||
|
Children({this.title, this.value, this.type, this.key, this.parent});
|
||||||
|
|
||||||
|
Children.fromJson(Map<String, dynamic> json) {
|
||||||
|
title = json['title'];
|
||||||
|
value = json['value'];
|
||||||
|
type = json['type'];
|
||||||
|
key = json['key'];
|
||||||
|
parent = json['parent'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['title'] = this.title;
|
||||||
|
data['value'] = this.value;
|
||||||
|
data['type'] = this.type;
|
||||||
|
data['key'] = this.key;
|
||||||
|
data['parent'] = this.parent;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ import 'package:qinglong_app/utils/extension.dart';
|
|||||||
/// @author NewTab
|
/// @author NewTab
|
||||||
class TaskLogDetailPage extends ConsumerStatefulWidget {
|
class TaskLogDetailPage extends ConsumerStatefulWidget {
|
||||||
final String title;
|
final String title;
|
||||||
|
final String path;
|
||||||
|
|
||||||
const TaskLogDetailPage({
|
const TaskLogDetailPage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
|
required this.path,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -38,21 +40,22 @@ class _TaskLogDetailPageState extends ConsumerState<TaskLogDetailPage> with Lazy
|
|||||||
body: content == null
|
body: content == null
|
||||||
? const Center(child: CupertinoActivityIndicator())
|
? const Center(child: CupertinoActivityIndicator())
|
||||||
: Padding(
|
: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 15,
|
horizontal: 15,
|
||||||
),
|
),
|
||||||
child: SelectableText(
|
child: SelectableText(
|
||||||
(content == null || content!.isEmpty) ? "暂无数据" : content!,
|
(content == null || content!.isEmpty) ? "暂无数据" : content!,
|
||||||
selectionHeightStyle: BoxHeightStyle.max,
|
selectionHeightStyle: BoxHeightStyle.max,
|
||||||
selectionWidthStyle: BoxWidthStyle.max,
|
selectionWidthStyle: BoxWidthStyle.max,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadData() async {
|
Future<void> loadData() async {
|
||||||
HttpResponse<String> response = await Api.taskLogDetail(
|
HttpResponse<String> response = await Api.taskLogDetail(
|
||||||
widget.title,
|
widget.title,
|
||||||
|
widget.path,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
|||||||
@@ -43,40 +43,66 @@ class _TaskLogPageState extends ConsumerState<TaskLogPage> with LazyLoadState<Ta
|
|||||||
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
child: (item.isDir ?? false)
|
child: (item.isDir ?? false)
|
||||||
? ExpansionTile(
|
? ExpansionTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
item.name ?? "",
|
item.name ?? "",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
children: item.files!
|
children: (item.files?.isNotEmpty ?? false)
|
||||||
.map((e) => ListTile(
|
? item.files!
|
||||||
onTap: () {
|
.map((e) => ListTile(
|
||||||
Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: item.name! + "/" + e);
|
onTap: () {
|
||||||
},
|
Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: {
|
||||||
title: Text(
|
"path": item.name,
|
||||||
e,
|
"title": e,
|
||||||
style: TextStyle(
|
});
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
},
|
||||||
fontSize: 14,
|
title: Text(
|
||||||
),
|
e,
|
||||||
),
|
style: TextStyle(
|
||||||
))
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
.toList(),
|
fontSize: 14,
|
||||||
)
|
|
||||||
: ListTile(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: item.name);
|
|
||||||
},
|
|
||||||
title: Text(
|
|
||||||
item.name ?? "",
|
|
||||||
style: TextStyle(
|
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList()
|
||||||
|
: (item.children ?? [])
|
||||||
|
.map((e) => ListTile(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: {
|
||||||
|
"path": item.name,
|
||||||
|
"title": e.title,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
e.title ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
: ListTile(
|
||||||
|
onTap: () {
|
||||||
|
if (item.isDir ?? false) {
|
||||||
|
"该文件夹为空".toast();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeTaskLogDetail, arguments: item.name);
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
item.name ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
itemCount: list.length,
|
itemCount: list.length,
|
||||||
|
|||||||
@@ -74,111 +74,113 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Column(
|
body: SingleChildScrollView(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
Padding(
|
children: [
|
||||||
padding: const EdgeInsets.symmetric(
|
Padding(
|
||||||
horizontal: 15,
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 15,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"名称:",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
focusNode: focusNode,
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||||
|
hintText: "请输入名称",
|
||||||
|
),
|
||||||
|
autofocus: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
Padding(
|
||||||
mainAxisSize: MainAxisSize.min,
|
padding: const EdgeInsets.symmetric(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
horizontal: 15,
|
||||||
children: [
|
),
|
||||||
const SizedBox(
|
child: Column(
|
||||||
height: 15,
|
mainAxisSize: MainAxisSize.min,
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const Text(
|
children: [
|
||||||
"名称:",
|
const SizedBox(
|
||||||
style: TextStyle(
|
height: 15,
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
),
|
||||||
),
|
const Text(
|
||||||
TextField(
|
"命令:",
|
||||||
focusNode: focusNode,
|
style: TextStyle(
|
||||||
controller: _nameController,
|
fontSize: 16,
|
||||||
decoration: const InputDecoration(
|
fontWeight: FontWeight.w600,
|
||||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
),
|
||||||
hintText: "请输入名称",
|
|
||||||
),
|
),
|
||||||
autofocus: false,
|
TextField(
|
||||||
),
|
controller: _commandController,
|
||||||
],
|
maxLines: 4,
|
||||||
|
minLines: 1,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||||
|
hintText: "请输入命令",
|
||||||
|
),
|
||||||
|
autofocus: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.symmetric(
|
||||||
padding: const EdgeInsets.symmetric(
|
horizontal: 15,
|
||||||
horizontal: 15,
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"定时:",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
controller: _cronController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
||||||
|
hintText: "请输入定时",
|
||||||
|
),
|
||||||
|
autofocus: false,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"定时的cron不校验是否正确",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
"命令:",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
controller: _commandController,
|
|
||||||
maxLines: 4,
|
|
||||||
minLines: 1,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
|
||||||
hintText: "请输入命令",
|
|
||||||
),
|
|
||||||
autofocus: false,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 15,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
"定时:",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
controller: _cronController,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5),
|
|
||||||
hintText: "请输入定时",
|
|
||||||
),
|
|
||||||
autofocus: false,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 5,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
"定时的cron不校验是否正确",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -206,7 +208,7 @@ class _AddTaskPageState extends ConsumerState<AddTaskPage> {
|
|||||||
taskBean.schedule = _cronController.text;
|
taskBean.schedule = _cronController.text;
|
||||||
HttpResponse<NullResponse> response = await Api.addTask(
|
HttpResponse<NullResponse> response = await Api.addTask(
|
||||||
_nameController.text, _commandController.text, _cronController.text,
|
_nameController.text, _commandController.text, _cronController.text,
|
||||||
id: taskBean.sId);
|
id: taskBean.id,);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
(widget.taskBean?.sId == null) ? "新增成功" : "修改成功".toast();
|
(widget.taskBean?.sId == null) ? "新增成功" : "修改成功".toast();
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ class TaskBean {
|
|||||||
String? schedule;
|
String? schedule;
|
||||||
bool? saved;
|
bool? saved;
|
||||||
String? sId;
|
String? sId;
|
||||||
|
int? id;
|
||||||
|
String? _id;
|
||||||
int? created;
|
int? created;
|
||||||
int? status;
|
int? status;
|
||||||
String? timestamp;
|
String? timestamp;
|
||||||
@@ -24,20 +26,22 @@ class TaskBean {
|
|||||||
|
|
||||||
TaskBean(
|
TaskBean(
|
||||||
{this.name,
|
{this.name,
|
||||||
this.command,
|
this.command,
|
||||||
this.schedule,
|
this.schedule,
|
||||||
this.saved,
|
this.saved,
|
||||||
this.sId,
|
this.sId,
|
||||||
this.created,
|
this.created,
|
||||||
this.status,
|
this.status,
|
||||||
this.timestamp,
|
this.timestamp,
|
||||||
this.isSystem,
|
this.isSystem,
|
||||||
this.isDisabled,
|
this.isDisabled,
|
||||||
this.logPath,
|
this.logPath,
|
||||||
this.isPinned,
|
this.isPinned,
|
||||||
this.lastExecutionTime,
|
this.lastExecutionTime,
|
||||||
this.lastRunningTime,
|
this.lastRunningTime,
|
||||||
this.pid});
|
this.pid});
|
||||||
|
|
||||||
|
get nId => _id;
|
||||||
|
|
||||||
TaskBean.fromJson(Map<String, dynamic> json) {
|
TaskBean.fromJson(Map<String, dynamic> json) {
|
||||||
try {
|
try {
|
||||||
@@ -45,6 +49,8 @@ class TaskBean {
|
|||||||
command = json['command'].toString();
|
command = json['command'].toString();
|
||||||
schedule = json['schedule'].toString();
|
schedule = json['schedule'].toString();
|
||||||
saved = json['saved'];
|
saved = json['saved'];
|
||||||
|
id = json['id'];
|
||||||
|
_id = json['_id'];
|
||||||
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
sId = json.containsKey('_id') ? json['_id'].toString() : (json.containsKey('id') ? json['id'].toString() : "");
|
||||||
created = int.tryParse(json['created'].toString());
|
created = int.tryParse(json['created'].toString());
|
||||||
status = json['status'];
|
status = json['status'];
|
||||||
|
|||||||
@@ -3,91 +3,41 @@ import 'dart:io';
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
import 'package:qinglong_app/base/base_state_widget.dart';
|
import 'package:qinglong_app/base/base_state_widget.dart';
|
||||||
import 'package:qinglong_app/base/routes.dart';
|
import 'package:qinglong_app/base/routes.dart';
|
||||||
import 'package:qinglong_app/base/theme.dart';
|
import 'package:qinglong_app/base/theme.dart';
|
||||||
import 'package:qinglong_app/base/ui/abs_underline_tabindicator.dart';
|
|
||||||
import 'package:qinglong_app/base/ui/empty_widget.dart';
|
|
||||||
import 'package:qinglong_app/base/ui/menu.dart';
|
|
||||||
import 'package:qinglong_app/base/ui/ql_context_menu.dart';
|
|
||||||
import 'package:qinglong_app/module/task/intime_log/intime_log_page.dart';
|
import 'package:qinglong_app/module/task/intime_log/intime_log_page.dart';
|
||||||
import 'package:qinglong_app/module/task/task_bean.dart';
|
import 'package:qinglong_app/module/task/task_bean.dart';
|
||||||
import 'package:qinglong_app/module/task/task_detail/task_detail_page.dart';
|
|
||||||
import 'package:qinglong_app/module/task/task_viewmodel.dart';
|
import 'package:qinglong_app/module/task/task_viewmodel.dart';
|
||||||
import 'package:qinglong_app/utils/utils.dart';
|
import 'package:qinglong_app/utils/utils.dart';
|
||||||
|
|
||||||
class TaskPage extends StatefulWidget {
|
class TaskPage extends ConsumerStatefulWidget {
|
||||||
const TaskPage({Key? key}) : super(key: key);
|
const TaskPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_TaskPageState createState() => _TaskPageState();
|
_TaskPageState createState() => _TaskPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TaskPageState extends State<TaskPage> {
|
class _TaskPageState extends ConsumerState<TaskPage> {
|
||||||
final TextEditingController _searchController = TextEditingController();
|
final TextEditingController _searchController = TextEditingController();
|
||||||
|
|
||||||
|
String currentState = TaskViewModel.allStr;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
_searchController.addListener(() {
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseStateWidget<TaskViewModel>(
|
return BaseStateWidget<TaskViewModel>(
|
||||||
builder: (ref, model, child) {
|
builder: (ref, model, child) {
|
||||||
return Column(
|
return body(model, getListByType(model), ref);
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
searchCell(ref),
|
|
||||||
Expanded(
|
|
||||||
child: DefaultTabController(
|
|
||||||
length: 5,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
TabBar(
|
|
||||||
tabs: const [
|
|
||||||
Tab(
|
|
||||||
text: "全部",
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: "正在运行",
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: "从未运行",
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: "拉库脚本",
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
text: "已禁用",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
isScrollable: true,
|
|
||||||
indicator: AbsUnderlineTabIndicator(
|
|
||||||
wantWidth: 20,
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
width: 2,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: TabBarView(
|
|
||||||
children: [
|
|
||||||
body(model, model.list, ref),
|
|
||||||
body(model, model.running, ref),
|
|
||||||
body(model, model.neverRunning, ref),
|
|
||||||
body(model, model.notScripts, ref),
|
|
||||||
body(model, model.disabled, ref),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
model: taskProvider,
|
model: taskProvider,
|
||||||
onReady: (viewModel) {
|
onReady: (viewModel) {
|
||||||
@@ -100,26 +50,51 @@ class _TaskPageState extends State<TaskPage> {
|
|||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
color: Theme.of(context).primaryColor,
|
color: Theme.of(context).primaryColor,
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
return model.loadData(false);
|
return model.loadData( false);
|
||||||
},
|
},
|
||||||
child: list.isEmpty
|
child: IconTheme(
|
||||||
? const EmptyWidget()
|
data: const IconThemeData(
|
||||||
: ListView.builder(
|
size: 25,
|
||||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
),
|
||||||
itemBuilder: (context, index) {
|
child: SlidableAutoCloseBehavior(
|
||||||
TaskBean item = list[index];
|
child: ListView.separated(
|
||||||
|
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||||
if (_searchController.text.isEmpty ||
|
itemBuilder: (context, index) {
|
||||||
(item.name?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
if (index == 0) {
|
||||||
(item.command?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
return searchCell(ref);
|
||||||
(item.schedule?.contains(_searchController.text.toLowerCase()) ?? false)) {
|
}
|
||||||
return TaskItemCell(item, ref);
|
TaskBean item = list[index - 1];
|
||||||
} else {
|
if (_searchController.text.isEmpty ||
|
||||||
return const SizedBox.shrink();
|
(item.name?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
||||||
}
|
(item.command?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
||||||
},
|
(item.schedule?.contains(_searchController.text.toLowerCase()) ?? false)) {
|
||||||
itemCount: list.length,
|
return TaskItemCell(item, ref);
|
||||||
),
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemCount: list.length + 1,
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
if (index == 0) return const SizedBox.shrink();
|
||||||
|
TaskBean item = list[index - 1];
|
||||||
|
if (_searchController.text.isEmpty ||
|
||||||
|
(item.name?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
||||||
|
(item.command?.toLowerCase().contains(_searchController.text.toLowerCase()) ?? false) ||
|
||||||
|
(item.schedule?.contains(_searchController.text.toLowerCase()) ?? false)) {
|
||||||
|
return Container(
|
||||||
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
|
child: const Divider(
|
||||||
|
height: 1,
|
||||||
|
indent: 15,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,41 +104,149 @@ class _TaskPageState extends State<TaskPage> {
|
|||||||
horizontal: 15,
|
horizontal: 15,
|
||||||
vertical: 10,
|
vertical: 10,
|
||||||
),
|
),
|
||||||
child: CupertinoSearchTextField(
|
child: Row(
|
||||||
onSubmitted: (value) {
|
children: [
|
||||||
setState(() {});
|
Expanded(
|
||||||
},
|
child: CupertinoSearchTextField(
|
||||||
onSuffixTap: () {
|
onSubmitted: (value) {
|
||||||
_searchController.text = "";
|
setState(() {});
|
||||||
setState(() {});
|
},
|
||||||
},
|
onSuffixTap: () {
|
||||||
controller: _searchController,
|
_searchController.text = "";
|
||||||
borderRadius: BorderRadius.circular(
|
setState(() {});
|
||||||
30,
|
},
|
||||||
),
|
controller: _searchController,
|
||||||
padding: const EdgeInsets.symmetric(
|
borderRadius: BorderRadius.circular(
|
||||||
horizontal: 5,
|
30,
|
||||||
vertical: 5,
|
),
|
||||||
),
|
padding: const EdgeInsets.symmetric(
|
||||||
suffixInsets: const EdgeInsets.only(
|
horizontal: 5,
|
||||||
right: 15,
|
vertical: 5,
|
||||||
),
|
),
|
||||||
prefixInsets: EdgeInsets.only(
|
suffixInsets: const EdgeInsets.only(
|
||||||
top: Platform.isAndroid ? 10 : 6,
|
right: 15,
|
||||||
bottom: 6,
|
),
|
||||||
left: 15,
|
prefixInsets: EdgeInsets.only(
|
||||||
),
|
top: Platform.isAndroid ? 10 : 6,
|
||||||
placeholderStyle: TextStyle(
|
bottom: 6,
|
||||||
fontSize: 16,
|
left: 15,
|
||||||
color: context.watch(themeProvider).themeColor.descColor(),
|
),
|
||||||
),
|
placeholderStyle: TextStyle(
|
||||||
style: const TextStyle(
|
fontSize: 16,
|
||||||
fontSize: 16,
|
color: context.watch(themeProvider).themeColor.descColor(),
|
||||||
),
|
),
|
||||||
placeholder: "搜索",
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
placeholder: "搜索",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: PopupMenuButton<String>(
|
||||||
|
onSelected: (String result) {
|
||||||
|
currentState = result;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
itemBuilder: (BuildContext context) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Text(
|
||||||
|
TaskViewModel.allStr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: currentState == TaskViewModel.allStr ? ref.watch(themeProvider).primaryColor : ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: TaskViewModel.allStr,
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Text(
|
||||||
|
TaskViewModel.runningStr,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
currentState == TaskViewModel.runningStr ? ref.watch(themeProvider).primaryColor : ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: TaskViewModel.runningStr,
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Text(
|
||||||
|
TaskViewModel.neverStr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: currentState == TaskViewModel.neverStr ? ref.watch(themeProvider).primaryColor : ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: TaskViewModel.neverStr,
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
TaskViewModel.notScriptStr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: currentState == TaskViewModel.notScriptStr
|
||||||
|
? ref.watch(themeProvider).primaryColor
|
||||||
|
: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: TaskViewModel.notScriptStr,
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Text(
|
||||||
|
TaskViewModel.disableStr,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color:
|
||||||
|
currentState == TaskViewModel.disableStr ? ref.watch(themeProvider).primaryColor : ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
value: TaskViewModel.disableStr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 10,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"筛选",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<TaskBean> getListByType(TaskViewModel model) {
|
||||||
|
if (currentState == TaskViewModel.allStr) {
|
||||||
|
return model.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentState == TaskViewModel.runningStr) {
|
||||||
|
return model.running;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentState == TaskViewModel.neverStr) {
|
||||||
|
return model.neverRunning;
|
||||||
|
}
|
||||||
|
if (currentState == TaskViewModel.notScriptStr) {
|
||||||
|
return model.notScripts;
|
||||||
|
}
|
||||||
|
if (currentState == TaskViewModel.disableStr) {
|
||||||
|
return model.disabled;
|
||||||
|
}
|
||||||
|
return model.list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TaskItemCell extends StatelessWidget {
|
class TaskItemCell extends StatelessWidget {
|
||||||
@@ -176,93 +259,91 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ColoredBox(
|
return ColoredBox(
|
||||||
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
child: QlCupertinoContextMenu(
|
child: Slidable(
|
||||||
bean: bean,
|
key: ValueKey(bean.sId),
|
||||||
actions: [
|
endActionPane: ActionPane(
|
||||||
QLCupertinoContextMenuAction(
|
motion: const StretchMotion(),
|
||||||
child: Text(
|
extentRatio: 0.7,
|
||||||
bean.status! == 1 ? "运行" : "停止运行",
|
|
||||||
),
|
|
||||||
trailingIcon: bean.status! == 1 ? CupertinoIcons.memories : CupertinoIcons.stop_circle,
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
if (bean.status! == 1) {
|
|
||||||
startCron(context, ref);
|
|
||||||
} else {
|
|
||||||
stopCron(context, ref);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
QLCupertinoContextMenuAction(
|
|
||||||
child: const Text("查看日志"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
logCron(context, ref);
|
|
||||||
},
|
|
||||||
trailingIcon: CupertinoIcons.clock,
|
|
||||||
),
|
|
||||||
QLCupertinoContextMenuAction(
|
|
||||||
child: const Text("编辑"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pushNamed(Routes.routeAddTask, arguments: bean);
|
|
||||||
},
|
|
||||||
trailingIcon: CupertinoIcons.pencil_outline,
|
|
||||||
),
|
|
||||||
QLCupertinoContextMenuAction(
|
|
||||||
child: Text(bean.isPinned! == 0 ? "置顶" : "取消置顶"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
pinTask();
|
|
||||||
},
|
|
||||||
trailingIcon: bean.isPinned! == 0 ? CupertinoIcons.pin : CupertinoIcons.pin_slash,
|
|
||||||
),
|
|
||||||
QLCupertinoContextMenuAction(
|
|
||||||
child: Text(bean.isDisabled! == 0 ? "禁用" : "启用"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
enableTask();
|
|
||||||
},
|
|
||||||
isDestructiveAction: true,
|
|
||||||
trailingIcon: bean.isDisabled! == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
|
||||||
),
|
|
||||||
QLCupertinoContextMenuAction(
|
|
||||||
child: const Text("删除"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
delTask(context, ref);
|
|
||||||
},
|
|
||||||
isDestructiveAction: true,
|
|
||||||
trailingIcon: CupertinoIcons.delete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
previewBuilder: (context, anima, child) {
|
|
||||||
bool isDark = ref.watch(themeProvider).darkMode;
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
|
||||||
child: Container(
|
|
||||||
color: isDark ? const Color(0xff333333) : Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: 5,
|
|
||||||
right: 5,
|
|
||||||
top: 5,
|
|
||||||
bottom: isDark ? 5 : 20,
|
|
||||||
),
|
|
||||||
child: SizedBox(
|
|
||||||
height: 200,
|
|
||||||
child: TaskDetailPage(
|
|
||||||
bean,
|
|
||||||
hideAppbar: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xff5D5E70),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeAddTask, arguments: bean);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.pencil_outline,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffF19A39),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
pinTask(context);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: bean.isPinned! == 0 ? CupertinoIcons.pin : CupertinoIcons.pin_slash,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffA356D6),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
enableTask(context);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: bean.isDisabled! == 0 ? Icons.dnd_forwardslash : Icons.check_circle_outline_sharp,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffEA4D3E),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
delTask(context, ref);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.delete,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
startActionPane: ActionPane(
|
||||||
|
motion: const StretchMotion(),
|
||||||
|
extentRatio: 0.4,
|
||||||
|
children: [
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xffD25535),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
if (bean.status! == 1) {
|
||||||
|
startCron(context, ref);
|
||||||
|
} else {
|
||||||
|
stopCron(context, ref);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: bean.status! == 1 ? CupertinoIcons.memories : CupertinoIcons.stop_circle,
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: const Color(0xff606467),
|
||||||
|
onPressed: (_) {
|
||||||
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
|
logCron(context, ref);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.text_justifyleft,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Material(
|
||||||
|
color: ref.watch(themeProvider).themeColor.settingBgColor(),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pushNamed(Routes.routeTaskDetail, arguments: bean);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
color: bean.isPinned == 1 ? ref.watch(themeProvider).themeColor.pinColor() : Colors.transparent,
|
color: bean.isPinned == 1 ? ref.watch(themeProvider).themeColor.pinColor() : Colors.transparent,
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
@@ -282,11 +363,21 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
bean.isDisabled == 1
|
||||||
|
? const Icon(
|
||||||
|
Icons.dnd_forwardslash,
|
||||||
|
size: 18,
|
||||||
|
color: Color(0xffEA4D3E),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
SizedBox(
|
||||||
|
width: bean.isDisabled == 1 ? 5 : 0,
|
||||||
|
),
|
||||||
bean.status == 1
|
bean.status == 1
|
||||||
? const SizedBox.shrink()
|
? const SizedBox.shrink()
|
||||||
: SizedBox(
|
: SizedBox(
|
||||||
width: 15,
|
width: 13,
|
||||||
height: 15,
|
height: 13,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
color: ref.watch(themeProvider).primaryColor,
|
color: ref.watch(themeProvider).primaryColor,
|
||||||
@@ -305,7 +396,7 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
color: ref.watch(themeProvider).themeColor.titleColor(),
|
color: ref.watch(themeProvider).themeColor.titleColor(),
|
||||||
fontSize: 18,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -328,37 +419,22 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 5,
|
||||||
),
|
),
|
||||||
Row(
|
Material(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
color: Colors.transparent,
|
||||||
children: [
|
child: Text(
|
||||||
bean.isDisabled == 1
|
bean.schedule ?? "",
|
||||||
? const Icon(
|
maxLines: 1,
|
||||||
Icons.dnd_forwardslash,
|
style: TextStyle(
|
||||||
size: 12,
|
overflow: TextOverflow.ellipsis,
|
||||||
color: Colors.red,
|
color: ref.watch(themeProvider).themeColor.descColor(),
|
||||||
)
|
fontSize: 12,
|
||||||
: const SizedBox.shrink(),
|
|
||||||
const SizedBox(
|
|
||||||
width: 5,
|
|
||||||
),
|
),
|
||||||
Material(
|
),
|
||||||
color: Colors.transparent,
|
|
||||||
child: Text(
|
|
||||||
bean.schedule ?? "",
|
|
||||||
maxLines: 1,
|
|
||||||
style: TextStyle(
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
color: ref.watch(themeProvider).themeColor.descColor(),
|
|
||||||
fontSize: 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 5,
|
||||||
),
|
),
|
||||||
Material(
|
Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
@@ -376,30 +452,27 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(
|
),
|
||||||
height: 1,
|
|
||||||
indent: 15,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
startCron(BuildContext context, WidgetRef ref) async {
|
startCron(BuildContext context, WidgetRef ref) async {
|
||||||
await ref.read(taskProvider).runCrons(bean.sId!);
|
await ref.read(taskProvider).runCrons( bean.sId!);
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
logCron(context, ref);
|
logCron(context, ref);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
stopCron(BuildContext context, WidgetRef ref) {
|
stopCron(BuildContext context, WidgetRef ref) {
|
||||||
ref.read(taskProvider).stopCrons(bean.sId!);
|
ref.read(taskProvider).stopCrons( bean.sId!);
|
||||||
}
|
}
|
||||||
|
|
||||||
logCron(BuildContext context, WidgetRef ref) {
|
logCron(BuildContext context, WidgetRef ref) {
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
showCupertinoDialog(
|
showCupertinoDialog(
|
||||||
|
useRootNavigator: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return CupertinoAlertDialog(
|
return CupertinoAlertDialog(
|
||||||
title: Text(
|
title: Text(
|
||||||
@@ -416,7 +489,7 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
ref.read(taskProvider).loadData(false);
|
ref.read(taskProvider).loadData( false);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -426,17 +499,18 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableTask() {
|
void enableTask(BuildContext context) {
|
||||||
ref.read(taskProvider).enableTask(bean.sId!, bean.isDisabled!);
|
ref.read(taskProvider).enableTask( bean.sId!, bean.isDisabled!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pinTask() {
|
void pinTask(BuildContext context) {
|
||||||
ref.read(taskProvider).pinTask(bean.sId!, bean.isPinned!);
|
ref.read(taskProvider).pinTask( bean.sId!, bean.isPinned!);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delTask(BuildContext context, WidgetRef ref) {
|
void delTask(BuildContext context, WidgetRef ref) {
|
||||||
showCupertinoDialog(
|
showCupertinoDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
useRootNavigator: false,
|
||||||
builder: (context) => CupertinoAlertDialog(
|
builder: (context) => CupertinoAlertDialog(
|
||||||
title: const Text("确认删除"),
|
title: const Text("确认删除"),
|
||||||
content: Text("确认删除定时任务 ${bean.name ?? ""} 吗"),
|
content: Text("确认删除定时任务 ${bean.name ?? ""} 吗"),
|
||||||
@@ -461,7 +535,7 @@ class TaskItemCell extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
ref.read(taskProvider).delCron(bean.sId!);
|
ref.watch(taskProvider.notifier).delCron(bean.sId!);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import 'package:qinglong_app/utils/extension.dart';
|
|||||||
var taskProvider = ChangeNotifierProvider((ref) => TaskViewModel());
|
var taskProvider = ChangeNotifierProvider((ref) => TaskViewModel());
|
||||||
|
|
||||||
class TaskViewModel extends BaseViewModel {
|
class TaskViewModel extends BaseViewModel {
|
||||||
|
static const String allStr = "全部脚本";
|
||||||
|
static const String runningStr = "正在运行";
|
||||||
|
static const String neverStr = "从未运行";
|
||||||
|
static const String notScriptStr = "拉库脚本";
|
||||||
|
static const String disableStr = "禁用脚本";
|
||||||
List<TaskBean> list = [];
|
List<TaskBean> list = [];
|
||||||
List<TaskBean> running = [];
|
List<TaskBean> running = [];
|
||||||
List<TaskBean> neverRunning = [];
|
List<TaskBean> neverRunning = [];
|
||||||
@@ -33,17 +38,85 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sortList() {
|
void sortList() {
|
||||||
|
List<TaskBean> p = [];
|
||||||
|
List<TaskBean> r = [];
|
||||||
|
List<TaskBean> d = [];
|
||||||
|
|
||||||
for (int i = 0; i < list.length; i++) {
|
for (int i = 0; i < list.length; i++) {
|
||||||
if (list[i].isPinned == 1) {
|
if (list[i].isPinned == 1) {
|
||||||
final TaskBean item = list.removeAt(i);
|
p.add(list.removeAt(i));
|
||||||
list.insert(0, item);
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list[i].status == 0) {
|
||||||
|
r.add(list.removeAt(i));
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (list[i].isDisabled == 1) {
|
||||||
|
d.add(list.removeAt(i));
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.sort((TaskBean a, TaskBean b) {
|
||||||
|
bool c = DateTime.fromMillisecondsSinceEpoch(a.created ?? 0).isBefore(DateTime.fromMillisecondsSinceEpoch(b.created ?? 0));
|
||||||
|
if (c == true) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
p.sort((a, b) {
|
||||||
|
return (a.isDisabled ?? 0) - (b.isDisabled ?? 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
p.sort((a, b) {
|
||||||
|
if (a.status == 0 && b.status == 0) {
|
||||||
|
bool c = DateTime.fromMillisecondsSinceEpoch(a.created ?? 0).isBefore(DateTime.fromMillisecondsSinceEpoch(b.created ?? 0));
|
||||||
|
if (c == true) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return (a.status ?? 0) - (b.status ?? 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
r.sort((a, b) {
|
||||||
|
bool c = DateTime.fromMillisecondsSinceEpoch(a.created ?? 0).isBefore(DateTime.fromMillisecondsSinceEpoch(b.created ?? 0));
|
||||||
|
if (c == true) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
d.sort((a, b) {
|
||||||
|
bool c = DateTime.fromMillisecondsSinceEpoch(a.created ?? 0).isBefore(DateTime.fromMillisecondsSinceEpoch(b.created ?? 0));
|
||||||
|
if (c == true) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
list.sort((a, b) {
|
||||||
|
bool c = DateTime.fromMillisecondsSinceEpoch(a.created ?? 0).isBefore(DateTime.fromMillisecondsSinceEpoch(b.created ?? 0));
|
||||||
|
if (c == true) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
list.insertAll(0, r);
|
||||||
|
list.insertAll(0, p);
|
||||||
|
list.addAll(d);
|
||||||
|
|
||||||
running.clear();
|
running.clear();
|
||||||
running.addAll(list.where((element) => element.status == 0));
|
running.addAll(list.where((element) => element.status == 0));
|
||||||
neverRunning.clear();
|
neverRunning.clear();
|
||||||
neverRunning.addAll(list.where((element) => element.lastRunningTime == null ));
|
neverRunning.addAll(list.where((element) => element.lastRunningTime == null));
|
||||||
notScripts.clear();
|
notScripts.clear();
|
||||||
notScripts.addAll(list.where((element) => (element.command != null && (element.command!.startsWith("ql repo") || element.command!.startsWith("ql raw")))));
|
notScripts.addAll(list.where((element) => (element.command != null && (element.command!.startsWith("ql repo") || element.command!.startsWith("ql raw")))));
|
||||||
disabled.clear();
|
disabled.clear();
|
||||||
@@ -53,9 +126,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
Future<void> runCrons(String cron) async {
|
Future<void> runCrons(String cron) async {
|
||||||
HttpResponse<NullResponse> result = await Api.startTasks([cron]);
|
HttpResponse<NullResponse> result = await Api.startTasks([cron]);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
list.firstWhere((element) => element.sId == cron).status = 0;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
notifyListeners();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(result.message, notify: true);
|
failToast(result.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -64,9 +135,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
Future<void> stopCrons(String cron) async {
|
Future<void> stopCrons(String cron) async {
|
||||||
HttpResponse<NullResponse> result = await Api.stopTasks([cron]);
|
HttpResponse<NullResponse> result = await Api.stopTasks([cron]);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
list.firstWhere((element) => element.sId == cron).status = 1;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
notifyListeners();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(result.message, notify: true);
|
failToast(result.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -75,9 +144,8 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
Future<void> delCron(String id) async {
|
Future<void> delCron(String id) async {
|
||||||
HttpResponse<NullResponse> result = await Api.delTask(id);
|
HttpResponse<NullResponse> result = await Api.delTask(id);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
list.removeWhere((element) => element.sId == id);
|
|
||||||
"删除成功".toast();
|
"删除成功".toast();
|
||||||
notifyListeners();
|
loadData(false);
|
||||||
} else {
|
} else {
|
||||||
failToast(result.message, notify: true);
|
failToast(result.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -101,9 +169,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
"取消置顶成功".toast();
|
"取消置顶成功".toast();
|
||||||
list.firstWhere((element) => element.sId == sId).isPinned = 0;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
success();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(response.message, notify: true);
|
failToast(response.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -112,9 +178,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
"置顶成功".toast();
|
"置顶成功".toast();
|
||||||
list.firstWhere((element) => element.sId == sId).isPinned = 1;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
success();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(response.message, notify: true);
|
failToast(response.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -127,9 +191,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
"禁用成功".toast();
|
"禁用成功".toast();
|
||||||
list.firstWhere((element) => element.sId == sId).isDisabled = 1;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
success();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(response.message, notify: true);
|
failToast(response.message, notify: true);
|
||||||
}
|
}
|
||||||
@@ -138,9 +200,7 @@ class TaskViewModel extends BaseViewModel {
|
|||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
"启用成功".toast();
|
"启用成功".toast();
|
||||||
list.firstWhere((element) => element.sId == sId).isDisabled = 0;
|
loadData(false);
|
||||||
sortList();
|
|
||||||
success();
|
|
||||||
} else {
|
} else {
|
||||||
failToast(response.message, notify: true);
|
failToast(response.message, notify: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,399 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
import 'package:qinglong_app/base/http/url.dart';
|
|
||||||
import 'package:qinglong_app/utils/extension.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
import '../main.dart';
|
|
||||||
|
|
||||||
/// @author NewTab
|
|
||||||
|
|
||||||
class UpdateUtils {
|
|
||||||
Future<String?> checkUpdate([bool remind = false]) async {
|
|
||||||
try {
|
|
||||||
if (!Platform.isAndroid) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
||||||
|
|
||||||
String version = packageInfo.version;
|
|
||||||
String url = Url.checkUpdateUrl;
|
|
||||||
Dio dio = Dio(BaseOptions(
|
|
||||||
connectTimeout: 50000,
|
|
||||||
receiveTimeout: 50000,
|
|
||||||
sendTimeout: 50000,
|
|
||||||
));
|
|
||||||
var response = await dio.get(url);
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
if (version == response.data as String) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return response.data as String;
|
|
||||||
}
|
|
||||||
} on DioError catch (e) {
|
|
||||||
if (remind) {
|
|
||||||
"无法连接到github服务器,版本更新检测失败".toast();
|
|
||||||
}
|
|
||||||
logger.e(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void launchURL(String version) async {
|
|
||||||
try {
|
|
||||||
await launch("https://github.com/qinglong-app/qinglong_app/releases/download/v$version/app-release-v$version.apk");
|
|
||||||
} catch (e) {
|
|
||||||
logger.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///版本更新加提示框
|
|
||||||
class UpdateDialog {
|
|
||||||
bool _isShowing = false;
|
|
||||||
late BuildContext _context;
|
|
||||||
late UpdateWidget _widget;
|
|
||||||
|
|
||||||
UpdateDialog(BuildContext context,
|
|
||||||
{double width = 0.0,
|
|
||||||
required String title,
|
|
||||||
required String updateContent,
|
|
||||||
required VoidCallback onUpdate,
|
|
||||||
double titleTextSize = 16.0,
|
|
||||||
double contentTextSize = 14.0,
|
|
||||||
double buttonTextSize = 14.0,
|
|
||||||
double progress = -1.0,
|
|
||||||
Color progressBackgroundColor = const Color(0xFFFFCDD2),
|
|
||||||
Image? topImage,
|
|
||||||
double extraHeight = 5.0,
|
|
||||||
double radius = 4.0,
|
|
||||||
Color themeColor = Colors.red,
|
|
||||||
bool enableIgnore = false,
|
|
||||||
VoidCallback? onIgnore,
|
|
||||||
bool isForce = false,
|
|
||||||
String? updateButtonText,
|
|
||||||
String? ignoreButtonText,
|
|
||||||
VoidCallback? onClose}) {
|
|
||||||
_context = context;
|
|
||||||
_widget = UpdateWidget(
|
|
||||||
width: width,
|
|
||||||
title: title,
|
|
||||||
updateContent: updateContent,
|
|
||||||
onUpdate: onUpdate,
|
|
||||||
titleTextSize: titleTextSize,
|
|
||||||
contentTextSize: contentTextSize,
|
|
||||||
buttonTextSize: buttonTextSize,
|
|
||||||
progress: progress,
|
|
||||||
topImage: topImage,
|
|
||||||
extraHeight: extraHeight,
|
|
||||||
radius: radius,
|
|
||||||
themeColor: themeColor,
|
|
||||||
progressBackgroundColor: progressBackgroundColor,
|
|
||||||
enableIgnore: enableIgnore,
|
|
||||||
onIgnore: onIgnore,
|
|
||||||
isForce: isForce,
|
|
||||||
updateButtonText: updateButtonText ?? '更新',
|
|
||||||
ignoreButtonText: ignoreButtonText ?? '忽略此版本',
|
|
||||||
onClose: onClose ?? () => dismiss());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 显示弹窗
|
|
||||||
Future<bool> show() {
|
|
||||||
try {
|
|
||||||
if (isShowing()) {
|
|
||||||
return Future<bool>.value(false);
|
|
||||||
}
|
|
||||||
showDialog<bool>(
|
|
||||||
context: _context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return WillPopScope(onWillPop: () => Future<bool>.value(false), child: _widget);
|
|
||||||
});
|
|
||||||
_isShowing = true;
|
|
||||||
return Future<bool>.value(true);
|
|
||||||
} catch (err) {
|
|
||||||
_isShowing = false;
|
|
||||||
return Future<bool>.value(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 隐藏弹窗
|
|
||||||
Future<bool> dismiss() {
|
|
||||||
try {
|
|
||||||
if (_isShowing) {
|
|
||||||
_isShowing = false;
|
|
||||||
Navigator.pop(_context);
|
|
||||||
return Future<bool>.value(true);
|
|
||||||
} else {
|
|
||||||
return Future<bool>.value(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return Future<bool>.value(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 是否显示
|
|
||||||
bool isShowing() {
|
|
||||||
return _isShowing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 更新进度
|
|
||||||
void update(double progress) {
|
|
||||||
if (isShowing()) {
|
|
||||||
_widget.update(progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 显示版本更新提示框
|
|
||||||
static UpdateDialog showUpdate(BuildContext context,
|
|
||||||
{double width = 0.0,
|
|
||||||
required String title,
|
|
||||||
required String updateContent,
|
|
||||||
required VoidCallback onUpdate,
|
|
||||||
double titleTextSize = 16.0,
|
|
||||||
double contentTextSize = 14.0,
|
|
||||||
double buttonTextSize = 14.0,
|
|
||||||
double progress = -1.0,
|
|
||||||
Color progressBackgroundColor = const Color(0xFFFFCDD2),
|
|
||||||
Image? topImage,
|
|
||||||
double extraHeight = 5.0,
|
|
||||||
double radius = 4.0,
|
|
||||||
Color themeColor = Colors.red,
|
|
||||||
bool enableIgnore = false,
|
|
||||||
VoidCallback? onIgnore,
|
|
||||||
String? updateButtonText,
|
|
||||||
String? ignoreButtonText,
|
|
||||||
bool isForce = false}) {
|
|
||||||
final UpdateDialog dialog = UpdateDialog(context,
|
|
||||||
width: width,
|
|
||||||
title: title,
|
|
||||||
updateContent: updateContent,
|
|
||||||
onUpdate: onUpdate,
|
|
||||||
titleTextSize: titleTextSize,
|
|
||||||
contentTextSize: contentTextSize,
|
|
||||||
buttonTextSize: buttonTextSize,
|
|
||||||
progress: progress,
|
|
||||||
topImage: topImage,
|
|
||||||
extraHeight: extraHeight,
|
|
||||||
radius: radius,
|
|
||||||
themeColor: themeColor,
|
|
||||||
progressBackgroundColor: progressBackgroundColor,
|
|
||||||
enableIgnore: enableIgnore,
|
|
||||||
isForce: isForce,
|
|
||||||
updateButtonText: updateButtonText,
|
|
||||||
ignoreButtonText: ignoreButtonText,
|
|
||||||
onIgnore: onIgnore);
|
|
||||||
dialog.show();
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
class UpdateWidget extends StatefulWidget {
|
|
||||||
/// 对话框的宽度
|
|
||||||
final double width;
|
|
||||||
|
|
||||||
/// 升级标题
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
/// 更新内容
|
|
||||||
final String updateContent;
|
|
||||||
|
|
||||||
/// 标题文字的大小
|
|
||||||
final double titleTextSize;
|
|
||||||
|
|
||||||
/// 更新文字内容的大小
|
|
||||||
final double contentTextSize;
|
|
||||||
|
|
||||||
/// 按钮文字的大小
|
|
||||||
final double buttonTextSize;
|
|
||||||
|
|
||||||
/// 顶部图片
|
|
||||||
final Widget? topImage;
|
|
||||||
|
|
||||||
/// 拓展高度(适配顶部图片高度不一致的情况)
|
|
||||||
final double extraHeight;
|
|
||||||
|
|
||||||
/// 边框圆角大小
|
|
||||||
final double radius;
|
|
||||||
|
|
||||||
/// 主题颜色
|
|
||||||
final Color themeColor;
|
|
||||||
|
|
||||||
/// 更新事件
|
|
||||||
final VoidCallback onUpdate;
|
|
||||||
|
|
||||||
/// 可忽略更新
|
|
||||||
final bool enableIgnore;
|
|
||||||
|
|
||||||
/// 更新事件
|
|
||||||
final VoidCallback? onIgnore;
|
|
||||||
|
|
||||||
double progress;
|
|
||||||
|
|
||||||
/// 进度条的背景颜色
|
|
||||||
final Color progressBackgroundColor;
|
|
||||||
|
|
||||||
/// 更新事件
|
|
||||||
final VoidCallback? onClose;
|
|
||||||
|
|
||||||
/// 是否是强制更新
|
|
||||||
final bool isForce;
|
|
||||||
|
|
||||||
/// 更新按钮内容
|
|
||||||
final String updateButtonText;
|
|
||||||
|
|
||||||
/// 忽略按钮内容
|
|
||||||
final String ignoreButtonText;
|
|
||||||
|
|
||||||
UpdateWidget(
|
|
||||||
{Key? key,
|
|
||||||
this.width = 0.0,
|
|
||||||
required this.title,
|
|
||||||
required this.updateContent,
|
|
||||||
required this.onUpdate,
|
|
||||||
this.titleTextSize = 16.0,
|
|
||||||
this.contentTextSize = 14.0,
|
|
||||||
this.buttonTextSize = 14.0,
|
|
||||||
this.progress = -1.0,
|
|
||||||
this.progressBackgroundColor = const Color(0xFFFFCDD2),
|
|
||||||
this.topImage,
|
|
||||||
this.extraHeight = 5.0,
|
|
||||||
this.radius = 4.0,
|
|
||||||
this.themeColor = Colors.red,
|
|
||||||
this.enableIgnore = false,
|
|
||||||
this.onIgnore,
|
|
||||||
this.isForce = false,
|
|
||||||
this.updateButtonText = '更新',
|
|
||||||
this.ignoreButtonText = '忽略此版本',
|
|
||||||
this.onClose})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
final _UpdateWidgetState _state = _UpdateWidgetState();
|
|
||||||
|
|
||||||
void update(double progress) {
|
|
||||||
_state.update(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
_UpdateWidgetState createState() => _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _UpdateWidgetState extends State<UpdateWidget> {
|
|
||||||
void update(double progress) {
|
|
||||||
if (!mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
widget.progress = progress;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final double dialogWidth = widget.width <= 0 ? getFitWidth(context) * 0.618 : widget.width;
|
|
||||||
return Material(
|
|
||||||
type: MaterialType.transparency,
|
|
||||||
child: SizedBox(
|
|
||||||
width: dialogWidth,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
SizedBox(
|
|
||||||
width: dialogWidth,
|
|
||||||
child: widget.topImage ?? Image.asset('assets/images/update_bg_app_top.png', fit: BoxFit.fill),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: dialogWidth,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 8),
|
|
||||||
decoration: ShapeDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(widget.radius), bottomRight: Radius.circular(widget.radius)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(top: widget.extraHeight),
|
|
||||||
child: Text(widget.title, style: TextStyle(fontSize: widget.titleTextSize, color: Colors.black)),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
||||||
child: Text(widget.updateContent, style: TextStyle(fontSize: widget.contentTextSize, color: const Color(0xFF666666))),
|
|
||||||
),
|
|
||||||
Column(children: <Widget>[
|
|
||||||
FractionallySizedBox(
|
|
||||||
widthFactor: 1,
|
|
||||||
child: ElevatedButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
textStyle: MaterialStateProperty.all(TextStyle(fontSize: widget.buttonTextSize)),
|
|
||||||
foregroundColor: MaterialStateProperty.all(Colors.white),
|
|
||||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))),
|
|
||||||
elevation: MaterialStateProperty.all(0),
|
|
||||||
backgroundColor: MaterialStateProperty.all(widget.themeColor),
|
|
||||||
),
|
|
||||||
child: Text(widget.updateButtonText),
|
|
||||||
onPressed: widget.onUpdate,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (widget.enableIgnore && widget.onIgnore != null)
|
|
||||||
FractionallySizedBox(
|
|
||||||
widthFactor: 1,
|
|
||||||
child: TextButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
textStyle: MaterialStateProperty.all(TextStyle(fontSize: widget.buttonTextSize)),
|
|
||||||
foregroundColor: MaterialStateProperty.all(const Color(0xFF666666)),
|
|
||||||
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))),
|
|
||||||
),
|
|
||||||
child: Text(widget.ignoreButtonText),
|
|
||||||
onPressed: widget.onIgnore,
|
|
||||||
))
|
|
||||||
else
|
|
||||||
const SizedBox()
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
if (!widget.isForce)
|
|
||||||
Column(children: <Widget>[
|
|
||||||
const SizedBox(width: 1.5, height: 50, child: DecoratedBox(decoration: BoxDecoration(color: Colors.white))),
|
|
||||||
IconButton(
|
|
||||||
iconSize: 30,
|
|
||||||
constraints: const BoxConstraints(maxHeight: 30, maxWidth: 30),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
icon: Image.asset(
|
|
||||||
'assets/images/update_ic_close.png',
|
|
||||||
),
|
|
||||||
onPressed: widget.onClose,
|
|
||||||
)
|
|
||||||
])
|
|
||||||
else
|
|
||||||
const SizedBox()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
double getFitWidth(BuildContext context) {
|
|
||||||
return min(getScreenHeight(context), getScreenWidth(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
double getScreenHeight(BuildContext context) {
|
|
||||||
return MediaQuery.of(context).size.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getScreenWidth(BuildContext context) {
|
|
||||||
return MediaQuery.of(context).size.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,32 +7,14 @@ class Utils {
|
|||||||
static final SystemBean systemBean = SystemBean();
|
static final SystemBean systemBean = SystemBean();
|
||||||
|
|
||||||
static bool isUpperVersion() {
|
static bool isUpperVersion() {
|
||||||
try {
|
return systemBean.isUpperVersion();
|
||||||
List<String>? version = Utils.systemBean.version?.split("\.");
|
}
|
||||||
|
static bool isUpperVersion2_12_2() {
|
||||||
|
return systemBean.isUpperVersion2_12_2();
|
||||||
|
}
|
||||||
|
|
||||||
String f = version?[0] ?? "2";
|
static bool isUpperVersion2_13_0() {
|
||||||
String s = version?[1] ?? "10";
|
return systemBean.isUpperVersion2_13_0();
|
||||||
String t = version?[2] ?? "0";
|
|
||||||
|
|
||||||
int first = int.parse(f);
|
|
||||||
int second = int.parse(s);
|
|
||||||
int third = int.parse(t);
|
|
||||||
|
|
||||||
/// 2.10.13 及以下版本
|
|
||||||
|
|
||||||
if (first > 2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (second > 10) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (third > 13) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hideKeyBoard(BuildContext context) {
|
static void hideKeyBoard(BuildContext context) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: qinglong_app
|
name: qinglong_app
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
version: 1.0.8+10
|
version: 1.0.9+11
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.15.1 <3.0.0"
|
sdk: ">=2.15.1 <3.0.0"
|
||||||
@@ -63,7 +63,7 @@ flutter:
|
|||||||
assets:
|
assets:
|
||||||
- assets/images/
|
- assets/images/
|
||||||
flutter_app_name:
|
flutter_app_name:
|
||||||
name: "青龙"
|
name: "青龙客户端"
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
image_path_android: "assets/images/ql.png"
|
image_path_android: "assets/images/ql.png"
|
||||||
|
|||||||
BIN
web/favicon.png
|
Before Width: | Height: | Size: 917 B |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 20 KiB |
112
web/index.html
@@ -1,112 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
|
||||||
If you are serving your web app in a path other than the root, change the
|
|
||||||
href value below to reflect the base path you are serving from.
|
|
||||||
|
|
||||||
The path provided below has to start and end with a slash "/" in order for
|
|
||||||
it to work correctly.
|
|
||||||
|
|
||||||
For more details:
|
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
|
||||||
|
|
||||||
This is a placeholder for base href that will be replaced by the value of
|
|
||||||
the `--base-href` argument provided to `flutter build`.
|
|
||||||
-->
|
|
||||||
<base href="$FLUTTER_BASE_HREF">
|
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
|
||||||
<meta name="description" content="A new Flutter project.">
|
|
||||||
|
|
||||||
<!-- iOS meta tags & icons -->
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
||||||
<meta name="apple-mobile-web-app-title" content="qinglong_app">
|
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
|
||||||
|
|
||||||
<!-- Favicon -->
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
|
||||||
|
|
||||||
<title>qinglong_app</title>
|
|
||||||
<link rel="manifest" href="manifest.json">
|
|
||||||
<script src="splash/splash.js"></script>
|
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
|
||||||
<link rel="stylesheet" type="text/css" href="splash/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<picture id="splash">
|
|
||||||
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">
|
|
||||||
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">
|
|
||||||
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt=""/>
|
|
||||||
</picture>
|
|
||||||
<!-- This script installs service_worker.js to provide PWA functionality to
|
|
||||||
application. For more information, see:
|
|
||||||
https://developers.google.com/web/fundamentals/primers/service-workers -->
|
|
||||||
<script>
|
|
||||||
var serviceWorkerVersion = null;
|
|
||||||
var scriptLoaded = false;
|
|
||||||
function loadMainDartJs() {
|
|
||||||
if (scriptLoaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scriptLoaded = true;
|
|
||||||
var scriptTag = document.createElement('script');
|
|
||||||
scriptTag.src = 'main.dart.js';
|
|
||||||
scriptTag.type = 'application/javascript';
|
|
||||||
document.body.append(scriptTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
// Service workers are supported. Use them.
|
|
||||||
window.addEventListener('load', function () {
|
|
||||||
// Wait for registration to finish before dropping the <script> tag.
|
|
||||||
// Otherwise, the browser will load the script multiple times,
|
|
||||||
// potentially different versions.
|
|
||||||
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
|
|
||||||
navigator.serviceWorker.register(serviceWorkerUrl)
|
|
||||||
.then((reg) => {
|
|
||||||
function waitForActivation(serviceWorker) {
|
|
||||||
serviceWorker.addEventListener('statechange', () => {
|
|
||||||
if (serviceWorker.state == 'activated') {
|
|
||||||
console.log('Installed new service worker.');
|
|
||||||
loadMainDartJs();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!reg.active && (reg.installing || reg.waiting)) {
|
|
||||||
// No active web worker and we have installed or are installing
|
|
||||||
// one for the first time. Simply wait for it to activate.
|
|
||||||
waitForActivation(reg.installing || reg.waiting);
|
|
||||||
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
|
|
||||||
// When the app updates the serviceWorkerVersion changes, so we
|
|
||||||
// need to ask the service worker to update.
|
|
||||||
console.log('New service worker available.');
|
|
||||||
reg.update();
|
|
||||||
waitForActivation(reg.installing);
|
|
||||||
} else {
|
|
||||||
// Existing service worker is still good.
|
|
||||||
console.log('Loading app from service worker.');
|
|
||||||
loadMainDartJs();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If service worker doesn't succeed in a reasonable amount of time,
|
|
||||||
// fallback to plaint <script> tag.
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!scriptLoaded) {
|
|
||||||
console.warn(
|
|
||||||
'Failed to load app from service worker. Falling back to plain <script> tag.',
|
|
||||||
);
|
|
||||||
loadMainDartJs();
|
|
||||||
}
|
|
||||||
}, 4000);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Service workers not supported. Just drop the <script> tag.
|
|
||||||
loadMainDartJs();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "qinglong_app",
|
|
||||||
"short_name": "qinglong_app",
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"background_color": "#0175C2",
|
|
||||||
"theme_color": "#0175C2",
|
|
||||||
"description": "A new Flutter project.",
|
|
||||||
"orientation": "portrait-primary",
|
|
||||||
"prefer_related_applications": false,
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "icons/Icon-192.png",
|
|
||||||
"sizes": "192x192",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "icons/Icon-512.png",
|
|
||||||
"sizes": "512x512",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "icons/Icon-maskable-192.png",
|
|
||||||
"sizes": "192x192",
|
|
||||||
"type": "image/png",
|
|
||||||
"purpose": "maskable"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "icons/Icon-maskable-512.png",
|
|
||||||
"sizes": "512x512",
|
|
||||||
"type": "image/png",
|
|
||||||
"purpose": "maskable"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB |