Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b9b8f0dbb | ||
|
|
5eb48b2717 | ||
|
|
5339cfca70 | ||
|
|
1462b2d0b8 | ||
|
|
3798a23183 | ||
|
|
ddaf916170 | ||
|
|
d6e37b058f | ||
|
|
2e9ad7d7cb | ||
|
|
190da74f66 | ||
|
|
f1315dda7f | ||
|
|
43e6105eb3 | ||
|
|
d785209eb6 | ||
|
|
da8b6a9010 | ||
|
|
1fd68722da | ||
|
|
c9a2c1d0e4 | ||
|
|
161f536a62 | ||
|
|
1a32e9944e | ||
|
|
6deb753198 | ||
|
|
4e33a98631 | ||
|
|
dcb9464d8f | ||
|
|
b94936b29f | ||
|
|
108d0a5a5b | ||
|
|
4814a2de28 | ||
|
|
5d8eeff502 | ||
|
|
0bc4087266 | ||
|
|
921209b901 | ||
|
|
fa9d754470 | ||
|
|
1f50a1f0f4 | ||
|
|
80e84c0421 | ||
|
|
5059872c3f | ||
|
|
8add244776 | ||
|
|
04e23fd7e4 | ||
|
|
336b11b808 | ||
|
|
8d9dba361c | ||
|
|
64ce3638cb | ||
|
|
f3ceb73f0e | ||
|
|
131dbe934c | ||
|
|
58288e89bd | ||
|
|
22c43c7124 | ||
|
|
2bf0b25ee5 | ||
|
|
3bc03c1364 | ||
|
|
490d71f8c9 | ||
|
|
edceb5900e | ||
|
|
e5ef28415b | ||
|
|
46b98df153 | ||
|
|
9f34021c90 | ||
|
|
8121eef839 | ||
|
|
da48d1f66c | ||
|
|
b167287c5b | ||
|
|
41f9da6bf8 | ||
|
|
e7c7fc8186 | ||
|
|
b950dd2d68 | ||
|
|
6d34de14d3 | ||
|
|
a5a84c0cdd | ||
|
|
701b1b811f | ||
|
|
97267cdfbf | ||
|
|
40ce37d230 | ||
|
|
8a9ade355c | ||
|
|
9bffec64b5 | ||
|
|
a03ee2ae0e | ||
|
|
ee889235fe | ||
|
|
94d6d80497 |
17
.github/workflows/release.yml
vendored
@@ -19,6 +19,9 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
- name: Install Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: 'stable'
|
||||
flutter-version: '3.22.2'
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
@@ -29,13 +32,18 @@ jobs:
|
||||
curl -u ${{ secrets.BASIC_AUTH }} -o android/key.properties ${{ secrets.URL_PREFIX }}key.properties
|
||||
- name: Build
|
||||
run: dart run fl_build -p android,linux
|
||||
- name: Rename for fdroid
|
||||
run: |
|
||||
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm64.apk
|
||||
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm.apk
|
||||
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_amd64.apk
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm64.apk
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm.apk
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.apk
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm64.apk
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm.apk
|
||||
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_amd64.apk
|
||||
${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.AppImage
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -68,6 +76,9 @@ jobs:
|
||||
# uses: actions/checkout@v4
|
||||
# - name: Install Flutter
|
||||
# uses: subosito/flutter-action@v2
|
||||
# with:
|
||||
# channel: 'stable'
|
||||
# flutter-version: '3.22.2'
|
||||
# - name: Build
|
||||
# run: dart run fl_build -p ios,mac
|
||||
# - name: Create Release
|
||||
|
||||
3
.gitignore
vendored
@@ -57,9 +57,10 @@ test.dart
|
||||
|
||||
# Linux release
|
||||
linux.AppDir
|
||||
ServerBox-x86_64.AppImage
|
||||
**/*.AppImage
|
||||
|
||||
untranlated.json
|
||||
|
||||
.vscode/settings.json
|
||||
more_build_data.json
|
||||
trans.txt
|
||||
|
||||
@@ -4,7 +4,6 @@ English | [简体中文](README_zh.md)
|
||||
|
||||
<p align="center">
|
||||
<img alt="lang" src="https://img.shields.io/badge/lang-dart-pink">
|
||||
<img alt="countly" src="https://img.shields.io/badge/analysis-countly-pink">
|
||||
<img alt="license" src="https://img.shields.io/badge/license-GPLv3-pink">
|
||||
</p>
|
||||
|
||||
@@ -14,10 +13,14 @@ A Flutter project which provide charts to display <a href="../../issues/43">Linu
|
||||
Especially thanks to <a href="https://github.com/TerminalStudio/dartssh2">dartssh2</a> & <a href="https://github.com/TerminalStudio/xterm.dart">xterm.dart</a>.
|
||||
</p>
|
||||
|
||||
|
||||
## ⬇️ Download
|
||||
🎉 **The `Android / Linux / Windows` version are now built via GitHub Actions**
|
||||
|
||||
[iOS & macOS](https://apps.apple.com/app/id6476033062) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_gpt_box/releases)
|
||||
[iOS & macOS](https://apps.apple.com/app/id1586449703) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_server_box/releases)
|
||||
|
||||
- All deprecated versions before `v930` can be found in [here](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid).
|
||||
- To prevent injection attacks and etc., please don't download from untrusted sources. eg: Gitee release is not related to this project.
|
||||
|
||||
|
||||
## 🔖 Feature
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
<p align="center">
|
||||
<img alt="lang" src="https://img.shields.io/badge/lang-dart-pink">
|
||||
<img alt="countly" src="https://img.shields.io/badge/analysis-countly-pink">
|
||||
<img alt="license" src="https://img.shields.io/badge/license-GPLv3-pink">
|
||||
</p>
|
||||
|
||||
@@ -18,7 +17,10 @@
|
||||
## ⬇️ Download
|
||||
🎉 **现在 `Android / Linux / Windows` 版本使用 GitHub Actions 构建**。
|
||||
|
||||
[iOS & macOS](https://apps.apple.com/app/id1586449703) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_gpt_box/releases)
|
||||
[iOS & macOS](https://apps.apple.com/app/id1586449703) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_server_box/releases)
|
||||
|
||||
- 所有 `v930` 之前的版本可以在 [这里](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid) 找到。
|
||||
- 为了防止注入攻击等,请不要从不受信任的来源下载。例如:Gitee 的发行包与该项目无关。
|
||||
|
||||
|
||||
## 🔖 特点
|
||||
|
||||
@@ -100,3 +100,14 @@ flutter {
|
||||
}
|
||||
|
||||
dependencies {}
|
||||
|
||||
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
|
||||
import com.android.build.OutputFile
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def abiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
|
||||
if (abiVersionCode != null) {
|
||||
output.versionCodeOverride = variant.versionCode * 10 + abiVersionCode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
android/app/proguard-rules.pro
vendored
@@ -1,7 +1 @@
|
||||
-keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-keep class com.jcraft.** { *; }
|
||||
|
||||
@@ -3,3 +3,4 @@ distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
|
||||
distributionSha256Sum=6001aba9b2204d26fa25a5800bb9382cf3ee01ccb78fe77317b2872336eb2f80
|
||||
|
||||
6
fastlane/metadata/android/en-US/full_description.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
A Flutter project which provide charts to display Linux server status and tools to manage server.
|
||||
Especially thanks to dartssh2 & xterm.dart.
|
||||
|
||||
* Status chart (CPU, Sensors, GPU...), SSH Term, SFTP, Docker & Pkg & Process...
|
||||
* Platform specific: Bio auth、Msg push、Home widget、watchOS App...
|
||||
* English, 简体中文; Deutsch, 繁體中文, Indonesian, Français, Dutch; Español, Русский язык, Português, 日本語
|
||||
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
A server status & toolbox app using Flutter
|
||||
1
fastlane/metadata/android/en-US/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
ServerBox
|
||||
7
fastlane/metadata/android/zh-CN/full_description.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
使用 Flutter 开发的 Linux 服务器工具箱,提供服务器状态图表和管理工具。
|
||||
特别感谢 dartssh2 & xterm.dart。
|
||||
|
||||
特点:
|
||||
* 状态图表(CPU、传感器、GPU 等), SSH 终端, SFTP, Docker & 包 & 进程管理器...
|
||||
* 特殊支持:生物认证、推送、桌面小部件、watchOS App、跟随系统颜色...
|
||||
* 本地化 (English, 简体中文, Español, Русский язык, Português, 日本語, Deutsch, 繁體中文, Indonesian, Français, Dutch
|
||||
BIN
fastlane/metadata/android/zh-CN/images/icon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/1.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/2.png
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/3.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/4.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/5.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
fastlane/metadata/android/zh-CN/images/phoneScreenshots/6.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
1
fastlane/metadata/android/zh-CN/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
使用 Flutter 开发的服务器状态和工具箱应用
|
||||
1
fastlane/metadata/android/zh-CN/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
ServerBox
|
||||
@@ -1,6 +1,4 @@
|
||||
PODS:
|
||||
- countly_flutter (24.4.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- file_picker (0.0.1):
|
||||
@@ -36,7 +34,6 @@ PODS:
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- countly_flutter (from `.symlinks/plugins/countly_flutter/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
@@ -55,8 +52,6 @@ DEPENDENCIES:
|
||||
- watch_connectivity (from `.symlinks/plugins/watch_connectivity/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
countly_flutter:
|
||||
:path: ".symlinks/plugins/countly_flutter/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
@@ -91,7 +86,6 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/watch_connectivity/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
countly_flutter: 56233d921c6b4e0a720774a39b8ee8110d6f8d91
|
||||
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
|
||||
file_picker: c79185e70b9b45728cde2a8d8da454e0cb43f287
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
|
||||
@@ -690,7 +690,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -700,7 +700,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -826,7 +826,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -836,7 +836,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -854,7 +854,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -864,7 +864,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -885,7 +885,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -898,7 +898,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
@@ -924,7 +924,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -937,7 +937,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -960,7 +960,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -973,7 +973,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -996,7 +996,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -1008,7 +1008,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||
@@ -1037,7 +1037,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -1049,7 +1049,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||
PRODUCT_NAME = ServerBox;
|
||||
@@ -1075,7 +1075,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 923;
|
||||
CURRENT_PROJECT_VERSION = 992;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -1087,7 +1087,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.923;
|
||||
MARKETING_VERSION = 1.0.992;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||
PRODUCT_NAME = ServerBox;
|
||||
|
||||
40
lib/app.dart
@@ -3,10 +3,14 @@ import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:fl_lib/l10n/gen_l10n/lib_l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/res/rebuild.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:toolbox/view/page/home/home.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/build_data.dart';
|
||||
import 'package:server_box/data/res/rebuild.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/view/page/home/home.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
|
||||
part 'intro.dart';
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
@@ -15,7 +19,7 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
_setup(context);
|
||||
return ListenableBuilder(
|
||||
listenable: RebuildNodes.app,
|
||||
listenable: RNodes.app,
|
||||
builder: (context, _) {
|
||||
if (!Stores.setting.useSystemPrimaryColor.fetch()) {
|
||||
UIs.colorSeed = Color(Stores.setting.primaryColor.fetch());
|
||||
@@ -71,6 +75,7 @@ class MyApp extends StatelessWidget {
|
||||
...AppLocalizations.localizationsDelegates,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localeListResolutionCallback: LocaleUtil.resolve,
|
||||
title: BuildData.name,
|
||||
themeMode: themeMode,
|
||||
theme: light,
|
||||
@@ -81,7 +86,30 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
Widget _buildAppContent(BuildContext ctx) {
|
||||
//if (Pros.app.isWearOS) return const WearHome();
|
||||
return const HomePage();
|
||||
return const _AppContent(
|
||||
intro: _IntroPage(),
|
||||
child: HomePage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// It's used for init settings related to [BuildContext]
|
||||
final class _AppContent extends StatelessWidget {
|
||||
final Widget child;
|
||||
final Widget intro;
|
||||
|
||||
const _AppContent({required this.child, required this.intro});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
context.setLibL10n();
|
||||
final appL10n = AppLocalizations.of(context);
|
||||
if (appL10n != null) l10n = appL10n;
|
||||
|
||||
final showIntro = Stores.setting.showIntro.fetch();
|
||||
if (showIntro) return intro;
|
||||
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
|
||||
abstract final class BgRunMC {
|
||||
static const _channel = MethodChannel('${Miscs.pkgName}/app_retain');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
abstract final class HomeWidgetMC {
|
||||
static const _channel = MethodChannel('${Miscs.pkgName}/home_widget');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:server_box/data/res/build_data.dart';
|
||||
|
||||
extension BuildDataX on BuildData {
|
||||
static const versionStr = 'v1.0.${BuildData.build}';
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:toolbox/view/page/backup.dart';
|
||||
import 'package:toolbox/view/page/container.dart';
|
||||
import 'package:toolbox/view/page/home/home.dart';
|
||||
import 'package:toolbox/view/page/iperf.dart';
|
||||
import 'package:toolbox/view/page/ping.dart';
|
||||
import 'package:toolbox/view/page/private_key/edit.dart';
|
||||
import 'package:toolbox/view/page/private_key/list.dart';
|
||||
import 'package:toolbox/view/page/pve.dart';
|
||||
import 'package:toolbox/view/page/server/detail/view.dart';
|
||||
import 'package:toolbox/view/page/setting/platform/android.dart';
|
||||
import 'package:toolbox/view/page/setting/platform/ios.dart';
|
||||
import 'package:toolbox/view/page/setting/seq/srv_func_seq.dart';
|
||||
import 'package:toolbox/view/page/snippet/result.dart';
|
||||
import 'package:toolbox/view/page/ssh/page.dart';
|
||||
import 'package:toolbox/view/page/setting/seq/virt_key.dart';
|
||||
import 'package:toolbox/view/page/storage/local.dart';
|
||||
import 'package:server_box/data/model/server/private_key_info.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/res/build_data.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/view/page/backup.dart';
|
||||
import 'package:server_box/view/page/container.dart';
|
||||
import 'package:server_box/view/page/home/home.dart';
|
||||
import 'package:server_box/view/page/iperf.dart';
|
||||
import 'package:server_box/view/page/ping.dart';
|
||||
import 'package:server_box/view/page/private_key/edit.dart';
|
||||
import 'package:server_box/view/page/private_key/list.dart';
|
||||
import 'package:server_box/view/page/pve.dart';
|
||||
import 'package:server_box/view/page/server/detail/view.dart';
|
||||
import 'package:server_box/view/page/setting/platform/android.dart';
|
||||
import 'package:server_box/view/page/setting/platform/ios.dart';
|
||||
import 'package:server_box/view/page/setting/seq/srv_func_seq.dart';
|
||||
import 'package:server_box/view/page/snippet/result.dart';
|
||||
import 'package:server_box/view/page/ssh/page.dart';
|
||||
import 'package:server_box/view/page/setting/seq/virt_key.dart';
|
||||
import 'package:server_box/view/page/storage/local.dart';
|
||||
|
||||
import '../data/model/server/snippet.dart';
|
||||
import '../view/page/editor.dart';
|
||||
@@ -102,12 +102,14 @@ class AppRoutes {
|
||||
Key? key,
|
||||
required ServerPrivateInfo spi,
|
||||
String? initCmd,
|
||||
Snippet? initSnippet,
|
||||
}) {
|
||||
return AppRoutes(
|
||||
SSHPage(
|
||||
key: key,
|
||||
spi: spi,
|
||||
initCmd: initCmd,
|
||||
initSnippet: initSnippet,
|
||||
),
|
||||
'ssh_term',
|
||||
);
|
||||
|
||||
@@ -2,14 +2,9 @@ import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||
|
||||
Future<String?> getToken() async {
|
||||
if (isIOS) {
|
||||
final plainNotificationToken = PlainNotificationToken();
|
||||
plainNotificationToken.requestPermission();
|
||||
|
||||
// If you want to wait until Permission dialog close,
|
||||
// you need wait changing setting registered.
|
||||
await plainNotificationToken.onIosSettingsRegistered.first;
|
||||
return await plainNotificationToken.getToken();
|
||||
}
|
||||
return null;
|
||||
if (!isIOS) return null;
|
||||
final instance = ApnsToken()..requestPermission();
|
||||
// Wait until Permission dialog closed
|
||||
await instance.onIosSettingsRegistered.first;
|
||||
return await instance.getToken();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'dart:async';
|
||||
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
|
||||
abstract final class KeybordInteractive {
|
||||
static FutureOr<List<String>?> defaultHandle(
|
||||
|
||||
@@ -5,9 +5,9 @@ import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:icloud_storage/icloud_storage.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/model/app/sync.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:server_box/data/model/app/backup.dart';
|
||||
import 'package:server_box/data/model/app/sync.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
|
||||
import '../../../data/model/app/error.dart';
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import 'dart:io';
|
||||
import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/app/backup.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:webdav_client/webdav_client.dart';
|
||||
|
||||
abstract final class Webdav {
|
||||
|
||||
@@ -3,13 +3,13 @@ import 'dart:io';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/model/server/snippet.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/rebuild.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/server/private_key_info.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/rebuild.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
const backupFormatVersion = 1;
|
||||
|
||||
@@ -170,7 +170,7 @@ class Backup {
|
||||
}
|
||||
|
||||
Pros.reload();
|
||||
RebuildNodes.app.rebuild();
|
||||
RNodes.app.build();
|
||||
|
||||
_logger.info('Restore success');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
enum ErrFrom {
|
||||
unknown,
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
typedef GhId = String;
|
||||
|
||||
extension GhIdX on GhId {
|
||||
String get url => 'https://github.com/$this';
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
enum ContainerMenu {
|
||||
start,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
part 'server_func.g.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/server/server.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
part 'net_view.g.dart';
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class RebuildNode implements Listenable {
|
||||
final List<VoidCallback> _listeners = [];
|
||||
|
||||
RebuildNode();
|
||||
|
||||
@override
|
||||
void addListener(VoidCallback listener) {
|
||||
_listeners.add(listener);
|
||||
}
|
||||
|
||||
@override
|
||||
void removeListener(VoidCallback listener) {
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
void rebuild() {
|
||||
for (var listener in _listeners) {
|
||||
listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
enum ServerDetailCards {
|
||||
about(Icons.info),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
import '../../res/build_data.dart';
|
||||
import '../server/system.dart';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/view/page/ping.dart';
|
||||
import 'package:toolbox/view/page/server/tab.dart';
|
||||
import 'package:toolbox/view/page/snippet/list.dart';
|
||||
import 'package:toolbox/view/page/ssh/tab.dart';
|
||||
import 'package:server_box/view/page/ping.dart';
|
||||
import 'package:server_box/view/page/server/tab.dart';
|
||||
import 'package:server_box/view/page/snippet/list.dart';
|
||||
import 'package:server_box/view/page/ssh/tab.dart';
|
||||
|
||||
enum AppTab {
|
||||
server,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/model/container/type.dart';
|
||||
import 'package:server_box/data/model/container/type.dart';
|
||||
|
||||
abstract final class ContainerImg {
|
||||
final String? repository = null;
|
||||
@@ -72,7 +72,7 @@ final class DockerImg implements ContainerImg {
|
||||
final String repository;
|
||||
final String size;
|
||||
@override
|
||||
final String tag;
|
||||
final String? tag;
|
||||
|
||||
DockerImg({
|
||||
required this.containers,
|
||||
@@ -95,14 +95,30 @@ final class DockerImg implements ContainerImg {
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory DockerImg.fromJson(Map<String, dynamic> json) => DockerImg(
|
||||
containers: json["Containers"],
|
||||
createdAt: json["CreatedAt"],
|
||||
id: json["ID"],
|
||||
repository: json["Repository"],
|
||||
size: json["Size"],
|
||||
tag: json["Tag"],
|
||||
);
|
||||
factory DockerImg.fromJson(Map<String, dynamic> json) {
|
||||
final containers = switch (json["Containers"]) {
|
||||
final String a => a,
|
||||
final Object? a => a.toString(),
|
||||
};
|
||||
final repo = switch (json["Repository"] ?? json["Names"]) {
|
||||
final String a => a,
|
||||
final List a => a.firstOrNull.toString(),
|
||||
final Object? a => a.toString(),
|
||||
};
|
||||
final size = switch (json["Size"]) {
|
||||
final String a => a,
|
||||
final int a => a.bytes2Str,
|
||||
final Object? a => a.toString(),
|
||||
};
|
||||
return DockerImg(
|
||||
containers: containers,
|
||||
createdAt: json["CreatedAt"],
|
||||
id: json["ID"] ?? json["Id"] ?? '',
|
||||
repository: repo,
|
||||
size: size,
|
||||
tag: json["Tag"],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"Containers": containers,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/container/type.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/container/type.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
|
||||
abstract final class ContainerPs {
|
||||
sealed class ContainerPs {
|
||||
final String? id = null;
|
||||
final String? image = null;
|
||||
String? get name;
|
||||
@@ -140,7 +141,10 @@ final class DockerPs implements ContainerPs {
|
||||
String? get cmd => null;
|
||||
|
||||
@override
|
||||
bool get running => state?.contains('Up ') ?? false;
|
||||
bool get running {
|
||||
if (state?.contains('Exited') == true) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
void parseStats(String s) {
|
||||
@@ -154,12 +158,12 @@ final class DockerPs implements ContainerPs {
|
||||
/// CONTAINER ID NAMES IMAGE STATUS
|
||||
/// a049d689e7a1 aria2-pro p3terx/aria2-pro Up 3 weeks
|
||||
factory DockerPs.parse(String raw) {
|
||||
final parts = raw.split(RegExp(r'\s{2,}'));
|
||||
final parts = raw.split(Miscs.multiBlankreg);
|
||||
return DockerPs(
|
||||
id: parts[0],
|
||||
names: parts[1],
|
||||
image: parts[2],
|
||||
state: parts[3],
|
||||
state: parts[1],
|
||||
names: parts[2],
|
||||
image: parts[3].trim(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:toolbox/data/model/container/image.dart';
|
||||
import 'package:toolbox/data/model/container/ps.dart';
|
||||
import 'package:server_box/data/model/container/image.dart';
|
||||
import 'package:server_box/data/model/container/ps.dart';
|
||||
|
||||
enum ContainerType {
|
||||
docker,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/data/model/server/dist.dart';
|
||||
import 'package:server_box/data/model/server/dist.dart';
|
||||
|
||||
enum PkgManager {
|
||||
apt,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/data/model/pkg/manager.dart';
|
||||
import 'package:server_box/data/model/pkg/manager.dart';
|
||||
|
||||
class UpgradePkgInfo {
|
||||
final PkgManager? _mgr;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:toolbox/data/model/server/time_seq.dart';
|
||||
import 'package:toolbox/data/res/status.dart';
|
||||
import 'package:server_box/data/model/server/time_seq.dart';
|
||||
import 'package:server_box/data/res/status.dart';
|
||||
|
||||
const _kCap = 30;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/model/server/time_seq.dart';
|
||||
import 'package:server_box/data/model/server/time_seq.dart';
|
||||
|
||||
import '../../res/misc.dart';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
enum PveResType {
|
||||
lxc,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
|
||||
final class SensorAdaptor {
|
||||
final String raw;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/server/battery.dart';
|
||||
import 'package:toolbox/data/model/server/conn.dart';
|
||||
import 'package:toolbox/data/model/server/cpu.dart';
|
||||
import 'package:toolbox/data/model/server/disk.dart';
|
||||
import 'package:toolbox/data/model/server/memory.dart';
|
||||
import 'package:toolbox/data/model/server/net_speed.dart';
|
||||
import 'package:toolbox/data/model/server/nvdia.dart';
|
||||
import 'package:toolbox/data/model/server/sensors.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
import 'package:toolbox/data/model/server/temp.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
import 'package:server_box/data/model/server/battery.dart';
|
||||
import 'package:server_box/data/model/server/conn.dart';
|
||||
import 'package:server_box/data/model/server/cpu.dart';
|
||||
import 'package:server_box/data/model/server/disk.dart';
|
||||
import 'package:server_box/data/model/server/memory.dart';
|
||||
import 'package:server_box/data/model/server/net_speed.dart';
|
||||
import 'package:server_box/data/model/server/nvdia.dart';
|
||||
import 'package:server_box/data/model/server/sensors.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/model/server/system.dart';
|
||||
import 'package:server_box/data/model/server/temp.dart';
|
||||
|
||||
import '../app/tag_pickable.dart';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:toolbox/data/model/server/custom.dart';
|
||||
import 'package:toolbox/data/model/server/server.dart';
|
||||
import 'package:toolbox/data/model/server/wol_cfg.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:server_box/data/model/server/custom.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/model/server/wol_cfg.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
|
||||
import '../app/error.dart';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/model/server/battery.dart';
|
||||
import 'package:toolbox/data/model/server/nvdia.dart';
|
||||
import 'package:toolbox/data/model/server/sensors.dart';
|
||||
import 'package:toolbox/data/model/server/server.dart';
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
import 'package:server_box/data/model/server/battery.dart';
|
||||
import 'package:server_box/data/model/server/nvdia.dart';
|
||||
import 'package:server_box/data/model/server/sensors.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/model/server/system.dart';
|
||||
|
||||
import '../app/shell_func.dart';
|
||||
import 'cpu.dart';
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
|
||||
import '../app/tag_pickable.dart';
|
||||
|
||||
@@ -53,19 +57,116 @@ class Snippet implements TagPickable {
|
||||
@override
|
||||
String get tagName => name;
|
||||
|
||||
String fmtWith(ServerPrivateInfo spi) {
|
||||
final fmted = script.replaceAllMapped(
|
||||
RegExp(r'\${.+?}'),
|
||||
static final fmtFinder = RegExp(r'\$\{[^{}]+\}');
|
||||
|
||||
String fmtWithSpi(ServerPrivateInfo spi) {
|
||||
return script.replaceAllMapped(
|
||||
fmtFinder,
|
||||
(match) {
|
||||
final key = match.group(0);
|
||||
final func = fmtArgs[key];
|
||||
if (func == null) {
|
||||
return key!;
|
||||
}
|
||||
return func(spi);
|
||||
if (func != null) return func(spi);
|
||||
// If not found, return the original content for further processing
|
||||
return key ?? '';
|
||||
},
|
||||
);
|
||||
return fmted;
|
||||
}
|
||||
|
||||
Future<void> runInTerm(
|
||||
Terminal terminal,
|
||||
ServerPrivateInfo spi, {
|
||||
bool autoEnter = false,
|
||||
}) async {
|
||||
final argsFmted = fmtWithSpi(spi);
|
||||
final matches = fmtFinder.allMatches(argsFmted);
|
||||
|
||||
/// There is no [TerminalKey] in the script
|
||||
if (matches.isEmpty) {
|
||||
terminal.textInput(argsFmted);
|
||||
if (autoEnter) terminal.keyInput(TerminalKey.enter);
|
||||
return;
|
||||
}
|
||||
|
||||
// Records all start and end indexes of the matches
|
||||
final (starts, ends) = matches.fold((<int>[], <int>[]), (pre, e) {
|
||||
pre.$1.add(e.start);
|
||||
pre.$2.add(e.end);
|
||||
return pre;
|
||||
});
|
||||
|
||||
// Check all indexes, `(idx + 1).start` must >= `idx.end`
|
||||
for (var i = 0; i < starts.length - 1; i++) {
|
||||
final lastEnd = ends[i];
|
||||
final nextStart = starts[i + 1];
|
||||
if (nextStart < lastEnd) {
|
||||
throw 'Invalid format: $nextStart < $lastEnd';
|
||||
}
|
||||
}
|
||||
|
||||
// Start term input
|
||||
if (starts.first > 0) {
|
||||
terminal.textInput(argsFmted.substring(0, starts.first));
|
||||
}
|
||||
|
||||
// Process matched
|
||||
for (var idx = 0; idx < starts.length; idx++) {
|
||||
final start = starts[idx];
|
||||
final end = ends[idx];
|
||||
final key = argsFmted.substring(start, end).toLowerCase();
|
||||
|
||||
// Special funcs
|
||||
final special = _find(SnippetFuncs.specialCtrl, key);
|
||||
if (special != null) {
|
||||
final raw = key.substring(special.key.length + 1, key.length - 1);
|
||||
await special.value((term: terminal, raw: raw));
|
||||
}
|
||||
|
||||
// Term keys
|
||||
final termKey = _find(fmtTermKeys, key);
|
||||
if (termKey != null) await _doTermKeys(terminal, termKey, key);
|
||||
}
|
||||
|
||||
// End term input
|
||||
if (ends.last < argsFmted.length) {
|
||||
terminal.textInput(argsFmted.substring(ends.last));
|
||||
}
|
||||
|
||||
if (autoEnter) terminal.keyInput(TerminalKey.enter);
|
||||
}
|
||||
|
||||
Future<void> _doTermKeys(
|
||||
Terminal terminal,
|
||||
MapEntry<String, TerminalKey> termKey,
|
||||
String key,
|
||||
) async {
|
||||
if (termKey.value == TerminalKey.enter) {
|
||||
terminal.keyInput(TerminalKey.enter);
|
||||
return;
|
||||
}
|
||||
|
||||
final ctrlAlt = switch (termKey.value) {
|
||||
TerminalKey.control => (ctrl: true, alt: false),
|
||||
TerminalKey.alt => (ctrl: false, alt: true),
|
||||
_ => (ctrl: false, alt: false),
|
||||
};
|
||||
|
||||
// `${ctrl+ad}` -> `ctrla + d`
|
||||
final chars = key.substring(termKey.key.length + 1, key.length - 1);
|
||||
if (chars.isEmpty) return;
|
||||
final ok = terminal.charInput(
|
||||
chars.codeUnitAt(0),
|
||||
ctrl: ctrlAlt.ctrl,
|
||||
alt: ctrlAlt.alt,
|
||||
);
|
||||
if (!ok) {
|
||||
Loggers.app.warning('Failed to input: $key');
|
||||
}
|
||||
|
||||
terminal.textInput(chars.substring(1));
|
||||
}
|
||||
|
||||
MapEntry<String, T>? _find<T>(Map<String, T> map, String key) {
|
||||
return map.entries.firstWhereOrNull((e) => key.startsWith(e.key));
|
||||
}
|
||||
|
||||
static final fmtArgs = {
|
||||
@@ -76,6 +177,12 @@ class Snippet implements TagPickable {
|
||||
r'${id}': (ServerPrivateInfo spi) => spi.id,
|
||||
r'${name}': (ServerPrivateInfo spi) => spi.name,
|
||||
};
|
||||
|
||||
/// r'${ctrl+ad}' -> TerminalKey.control, a, d
|
||||
static final fmtTermKeys = {
|
||||
r'${ctrl': TerminalKey.control,
|
||||
r'${alt': TerminalKey.alt,
|
||||
};
|
||||
}
|
||||
|
||||
class SnippetResult {
|
||||
@@ -89,3 +196,32 @@ class SnippetResult {
|
||||
required this.time,
|
||||
});
|
||||
}
|
||||
|
||||
typedef SnippetFuncCtx = ({Terminal term, String raw});
|
||||
|
||||
abstract final class SnippetFuncs {
|
||||
static final specialCtrl = {
|
||||
// `${sleep 3}` -> sleep 3 seconds
|
||||
r'${sleep': SnippetFuncs.sleep,
|
||||
r'${enter': SnippetFuncs.enter,
|
||||
};
|
||||
|
||||
static const help = {
|
||||
'sleep': 'Sleep for a few seconds',
|
||||
'enter': 'Enter a few times',
|
||||
};
|
||||
|
||||
static FutureOr<void> sleep(SnippetFuncCtx ctx) async {
|
||||
final seconds = int.tryParse(ctx.raw);
|
||||
if (seconds == null) return;
|
||||
final duration = Duration(seconds: seconds);
|
||||
await Future.delayed(duration);
|
||||
}
|
||||
|
||||
static FutureOr<void> enter(SnippetFuncCtx ctx) async {
|
||||
final times = int.tryParse(ctx.raw) ?? 1;
|
||||
for (var i = 0; i < times; i++) {
|
||||
ctx.term.keyInput(TerminalKey.enter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
|
||||
enum SystemType {
|
||||
linux._(linuxSign),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
class TryLimiter {
|
||||
final Map<String, int> _triedTimes = {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:toolbox/data/model/sftp/absolute_path.dart';
|
||||
import 'package:server_box/data/model/sftp/absolute_path.dart';
|
||||
|
||||
class SftpBrowserStatus {
|
||||
List<SftpName>? files;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import '../../../core/utils/server.dart';
|
||||
import '../server/server_private_info.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
|
||||
part 'virtual_key.g.dart';
|
||||
|
||||
@@ -4,13 +4,13 @@ import 'dart:convert';
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/container/image.dart';
|
||||
import 'package:toolbox/data/model/container/ps.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/model/container/type.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/ssh_client.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
import 'package:server_box/data/model/container/image.dart';
|
||||
import 'package:server_box/data/model/container/ps.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/model/container/type.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
final _dockerNotFound =
|
||||
RegExp(r"command not found|Unknown command|Command '\w+' not found");
|
||||
@@ -160,11 +160,18 @@ class ContainerProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// Parse images
|
||||
final imageRaw = ContainerCmdType.images.find(segments);
|
||||
final imageRaw = ContainerCmdType.images.find(segments).trim();
|
||||
final isEntireJson = imageRaw.startsWith('[') && imageRaw.endsWith(']');
|
||||
try {
|
||||
final imgLines = imageRaw.split('\n');
|
||||
imgLines.removeWhere((element) => element.isEmpty);
|
||||
images = imgLines.map((e) => ContainerImg.fromRawJson(e, type)).toList();
|
||||
if (isEntireJson) {
|
||||
images = (json.decode(imageRaw) as List)
|
||||
.map((e) => ContainerImg.fromRawJson(json.encode(e), type))
|
||||
.toList();
|
||||
} else {
|
||||
final lines = imageRaw.split('\n');
|
||||
lines.removeWhere((element) => element.isEmpty);
|
||||
images = lines.map((e) => ContainerImg.fromRawJson(e, type)).toList();
|
||||
}
|
||||
} catch (e, trace) {
|
||||
error = ContainerErr(
|
||||
type: ContainerErrType.parseImages,
|
||||
@@ -276,9 +283,13 @@ enum ContainerCmdType {
|
||||
return switch (this) {
|
||||
ContainerCmdType.version => '$prefix version $_jsonFmt',
|
||||
ContainerCmdType.ps => switch (type) {
|
||||
/// TODO: Rollback to json format when permformance recovers.
|
||||
/// Use [_jsonFmt] in Docker will cause the operation to slow down.
|
||||
ContainerType.docker => '$prefix ps -a --format "table '
|
||||
'{{printf \\"${"%-30.30s " * 4}\\" .ID .Names .Image .Status}}"',
|
||||
ContainerType.docker => '$prefix ps -a --format "table {{printf \\"'
|
||||
'%-15.15s '
|
||||
'%-30.30s '
|
||||
'${"%-50.50s " * 2}\\"'
|
||||
' .ID .Status .Names .Image}}"',
|
||||
ContainerType.podman => '$prefix ps -a $_jsonFmt',
|
||||
},
|
||||
ContainerCmdType.stats =>
|
||||
@@ -294,6 +305,6 @@ enum ContainerCmdType {
|
||||
}) {
|
||||
return ContainerCmdType.values
|
||||
.map((e) => e.exec(type, sudo: sudo, includeStats: includeStats))
|
||||
.join(' && echo ${ShellFunc.seperator} && ');
|
||||
.join('\necho ${ShellFunc.seperator}\n');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/server/private_key_info.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
class PrivateKeyProvider extends ChangeNotifier {
|
||||
List<PrivateKeyInfo> get pkis => _pkis;
|
||||
|
||||
@@ -6,10 +6,10 @@ import 'package:dio/dio.dart';
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/model/server/pve.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/model/server/pve.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
|
||||
typedef PveCtrlFunc = Future<bool> Function(String node, String id);
|
||||
|
||||
@@ -5,20 +5,19 @@ import 'package:computer/computer.dart';
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||
import 'package:toolbox/core/utils/ssh_auth.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
import 'package:toolbox/data/model/sftp/req.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/ssh_client.dart';
|
||||
import 'package:server_box/core/utils/ssh_auth.dart';
|
||||
import 'package:server_box/data/model/app/error.dart';
|
||||
import 'package:server_box/data/model/app/shell_func.dart';
|
||||
import 'package:server_box/data/model/server/system.dart';
|
||||
import 'package:server_box/data/model/sftp/req.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import '../../core/utils/server.dart';
|
||||
import '../model/server/server.dart';
|
||||
import '../model/server/server_private_info.dart';
|
||||
import '../model/server/server_status_update_req.dart';
|
||||
import '../model/server/snippet.dart';
|
||||
import '../model/server/try_limiter.dart';
|
||||
import '../res/status.dart';
|
||||
|
||||
@@ -460,20 +459,20 @@ class ServerProvider extends ChangeNotifier {
|
||||
TryLimiter.reset(sid);
|
||||
}
|
||||
|
||||
Future<SnippetResult?> runSnippet(String id, Snippet snippet) async {
|
||||
final server = _servers[id];
|
||||
if (server == null) return null;
|
||||
final watch = Stopwatch()..start();
|
||||
final result = await server.client?.run(snippet.fmtWith(server.spi)).string;
|
||||
final time = watch.elapsed;
|
||||
watch.stop();
|
||||
if (result == null) return null;
|
||||
return SnippetResult(
|
||||
dest: _servers[id]?.spi.name,
|
||||
result: result,
|
||||
time: time,
|
||||
);
|
||||
}
|
||||
// Future<SnippetResult?> runSnippet(String id, Snippet snippet) async {
|
||||
// final server = _servers[id];
|
||||
// if (server == null) return null;
|
||||
// final watch = Stopwatch()..start();
|
||||
// final result = await server.client?.run(snippet.fmtWithArgs(server.spi)).string;
|
||||
// final time = watch.elapsed;
|
||||
// watch.stop();
|
||||
// if (result == null) return null;
|
||||
// return SnippetResult(
|
||||
// dest: _servers[id]?.spi.name,
|
||||
// result: result,
|
||||
// time: time,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Future<List<SnippetResult?>> runSnippetsMulti(
|
||||
// List<String> ids,
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'dart:convert';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/data/model/server/snippet.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
class SnippetProvider extends ChangeNotifier {
|
||||
late List<Snippet> _snippets;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
|
||||
class VirtKeyProvider extends TerminalInputHandler with ChangeNotifier {
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 923;
|
||||
static const String engine = "3.22.1";
|
||||
static const String buildAt = "2024-06-01 22:31:14";
|
||||
static const int modifications = 4;
|
||||
static const int script = 48;
|
||||
static const int build = 992;
|
||||
static const int script = 49;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import 'package:toolbox/data/model/app/github_id.dart';
|
||||
|
||||
abstract final class GithubIds {
|
||||
// Thanks
|
||||
// If you want to change your Github ID, please open an issue.
|
||||
static const contributors = <GhId>{
|
||||
'PaperCube',
|
||||
'Integral-Tech',
|
||||
'its-tom',
|
||||
'leganck',
|
||||
'azkadev',
|
||||
'kalashnikov',
|
||||
'FrancXPT',
|
||||
'RainSunMe',
|
||||
'calvinweb',
|
||||
'QazCetelic',
|
||||
'RainSunMe',
|
||||
'FrancXPT',
|
||||
'Liloupar',
|
||||
'dccif',
|
||||
'QazCetelic',
|
||||
};
|
||||
|
||||
static const participants = <GhId>{
|
||||
@@ -73,5 +73,22 @@ abstract final class GithubIds {
|
||||
'FHU-yezi',
|
||||
'ZRY233',
|
||||
'Jasonzhu1207',
|
||||
'sakuraanzu',
|
||||
'licaon-kter',
|
||||
'77160860',
|
||||
'mijjjj',
|
||||
'muyunil',
|
||||
'Hua159',
|
||||
'jaydong2016',
|
||||
'geol',
|
||||
'Mooling0602',
|
||||
'IllTamer',
|
||||
'marlkiller',
|
||||
};
|
||||
}
|
||||
|
||||
typedef GhId = String;
|
||||
|
||||
extension GhIdX on GhId {
|
||||
String get url => 'https://github.com/$this';
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
|
||||
abstract final class Miscs {
|
||||
static final blankReg = RegExp(r'\s+');
|
||||
static final multiBlankreg = RegExp(r'\s{2,}');
|
||||
|
||||
/// RegExp for password request
|
||||
static final pwdRequestWithUserReg = RegExp(r'\[sudo\] password for (.+):');
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/provider/app.dart';
|
||||
import 'package:toolbox/data/provider/private_key.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/provider/sftp.dart';
|
||||
import 'package:toolbox/data/provider/snippet.dart';
|
||||
import 'package:server_box/data/provider/app.dart';
|
||||
import 'package:server_box/data/provider/private_key.dart';
|
||||
import 'package:server_box/data/provider/server.dart';
|
||||
import 'package:server_box/data/provider/sftp.dart';
|
||||
import 'package:server_box/data/provider/snippet.dart';
|
||||
|
||||
abstract final class Pros {
|
||||
static final app = AppProvider();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:toolbox/data/model/app/rebuild.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
|
||||
abstract final class RebuildNodes {
|
||||
static final app = RebuildNode();
|
||||
abstract final class RNodes {
|
||||
static final app = RNode();
|
||||
static final dark = false.vn;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:toolbox/data/model/server/server.dart';
|
||||
import 'package:toolbox/data/model/server/temp.dart';
|
||||
import 'package:server_box/data/model/server/server.dart';
|
||||
import 'package:server_box/data/model/server/temp.dart';
|
||||
|
||||
import '../model/server/cpu.dart';
|
||||
import '../model/server/disk.dart';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/store/container.dart';
|
||||
import 'package:toolbox/data/store/history.dart';
|
||||
import 'package:toolbox/data/store/private_key.dart';
|
||||
import 'package:toolbox/data/store/server.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/data/store/snippet.dart';
|
||||
import 'package:server_box/data/store/container.dart';
|
||||
import 'package:server_box/data/store/history.dart';
|
||||
import 'package:server_box/data/store/private_key.dart';
|
||||
import 'package:server_box/data/store/server.dart';
|
||||
import 'package:server_box/data/store/setting.dart';
|
||||
import 'package:server_box/data/store/snippet.dart';
|
||||
|
||||
abstract final class Stores {
|
||||
static final setting = SettingStore();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
abstract final class Urls {
|
||||
static const cdnBase = 'https://cdn.lolli.tech/serverbox';
|
||||
static const updateCfg = '$cdnBase/update.json';
|
||||
static const updateCfg = '$cdnBase/update2.json';
|
||||
static const myGithub = 'https://github.com/lollipopkit';
|
||||
static const appHelp = '$myGithub/flutter_server_box#-help';
|
||||
static const appWiki = '$myGithub/flutter_server_box/wiki';
|
||||
static const thisRepo = '$myGithub/flutter_server_box';
|
||||
static const appHelp = '$thisRepo#-help';
|
||||
static const appWiki = '$thisRepo/wiki';
|
||||
static const analysis = 'https://countly.lolli.tech';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/model/container/type.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/data/model/container/type.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
const _keyConfig = 'providerConfig';
|
||||
|
||||
|
||||
@@ -54,4 +54,7 @@ class HistoryStore extends PersistentStore {
|
||||
late final sftpLastPath = _MapHistory(box: box, name: 'sftpLastPath');
|
||||
|
||||
late final sshCmds = _ListHistory(box: box, name: 'sshCmds');
|
||||
|
||||
/// Notify users that this app will write script to server to works properly
|
||||
late final writeScriptTipShown = property('writeScriptTipShown', false);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:toolbox/data/model/app/menu/server_func.dart';
|
||||
import 'package:toolbox/data/model/app/server_detail_card.dart';
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
import 'package:server_box/data/model/app/menu/server_func.dart';
|
||||
import 'package:server_box/data/model/app/server_detail_card.dart';
|
||||
import 'package:server_box/data/model/ssh/virtual_key.dart';
|
||||
|
||||
import '../model/app/net_view.dart';
|
||||
import '../res/default.dart';
|
||||
@@ -265,8 +265,6 @@ class SettingStore extends PersistentStore {
|
||||
|
||||
late final horizonVirtKey = property('horizonVirtKey', false);
|
||||
|
||||
late final collectUsage = property('collectUsage', true);
|
||||
|
||||
/// general wake lock
|
||||
late final generalWakeLock = property('generalWakeLock', false);
|
||||
|
||||
@@ -276,6 +274,14 @@ class SettingStore extends PersistentStore {
|
||||
/// fmt: https://example.com/{DIST}-{BRIGHT}.png
|
||||
late final serverLogoUrl = property('serverLogoUrl', '');
|
||||
|
||||
late final betaTest = property('betaTest', false);
|
||||
|
||||
/// If it's empty, skip change window size.
|
||||
/// Format: {width}x{height}
|
||||
late final windowSize = property('windowSize', '');
|
||||
|
||||
late final showIntro = property('showIntro', true);
|
||||
|
||||
// Never show these settings for users
|
||||
//
|
||||
// ------BEGIN------
|
||||
|
||||
107
lib/intro.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
part of 'app.dart';
|
||||
|
||||
final class _IntroPage extends StatelessWidget {
|
||||
const _IntroPage();
|
||||
|
||||
static final _setting = Stores.setting;
|
||||
static const _kIconSize = 23.0;
|
||||
static const _introListPad = EdgeInsets.symmetric(horizontal: 17);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, cons) {
|
||||
final padTop = cons.maxHeight * .2;
|
||||
return IntroPage(
|
||||
pages: [
|
||||
_buildAppSettings(context, padTop),
|
||||
_buildRecommended(context, padTop),
|
||||
],
|
||||
onDone: (ctx) {
|
||||
Stores.setting.showIntro.put(false);
|
||||
Navigator.of(ctx).pushReplacement(
|
||||
MaterialPageRoute(builder: (_) => const HomePage()),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRecommended(BuildContext context, double padTop) {
|
||||
return ListView(
|
||||
padding: _introListPad,
|
||||
children: [
|
||||
SizedBox(height: padTop),
|
||||
const Icon(Bootstrap.stars, size: 35),
|
||||
SizedBox(height: padTop),
|
||||
ListTile(
|
||||
leading: const Icon(MingCute.delete_2_fill),
|
||||
title: const Text('rm -r'),
|
||||
subtitle: Text(l10n.sftpRmrDirSummary, style: UIs.textGrey),
|
||||
trailing: StoreSwitch(prop: _setting.sftpRmrDir),
|
||||
).cardx,
|
||||
ListTile(
|
||||
leading: const Icon(IonIcons.stats_chart, size: _kIconSize),
|
||||
title: Text(l10n.parseContainerStats),
|
||||
subtitle: Text(l10n.parseContainerStatsTip, style: UIs.textGrey),
|
||||
trailing: StoreSwitch(prop: _setting.containerParseStat),
|
||||
).cardx,
|
||||
ListTile(
|
||||
leading: const Icon(OctIcons.cpu),
|
||||
title: Text('CPU ${l10n.noLineChart}'),
|
||||
subtitle: Text(l10n.cpuViewAsProgressTip, style: UIs.textGrey),
|
||||
trailing: StoreSwitch(prop: _setting.cpuViewAsProgress),
|
||||
).cardx,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppSettings(BuildContext ctx, double padTop) {
|
||||
return ListView(
|
||||
padding: _introListPad,
|
||||
children: [
|
||||
SizedBox(height: padTop),
|
||||
_buildTitle(l10n.init, big: true),
|
||||
SizedBox(height: padTop),
|
||||
ListTile(
|
||||
leading: const Icon(IonIcons.language),
|
||||
title: Text(l10n.language),
|
||||
onTap: () async {
|
||||
final selected = await ctx.showPickSingleDialog(
|
||||
title: l10n.language,
|
||||
items: AppLocalizations.supportedLocales,
|
||||
name: (p0) => p0.code,
|
||||
initial: _setting.locale.fetch().toLocale,
|
||||
);
|
||||
if (selected != null) {
|
||||
_setting.locale.put(selected.code);
|
||||
RNodes.app.build();
|
||||
}
|
||||
},
|
||||
trailing: Text(
|
||||
l10n.languageName,
|
||||
style: const TextStyle(fontSize: 15, color: Colors.grey),
|
||||
),
|
||||
).cardx,
|
||||
ListTile(
|
||||
leading: const Icon(Icons.update),
|
||||
title: Text(l10n.autoCheckUpdate),
|
||||
subtitle: Text(l10n.fdroidReleaseTip, style: UIs.textGrey),
|
||||
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
|
||||
).cardx,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTitle(String text, {bool big = false}) {
|
||||
return Center(
|
||||
child: Text(
|
||||
text,
|
||||
style: big
|
||||
? const TextStyle(fontSize: 41, fontWeight: FontWeight.w500)
|
||||
: UIs.textGrey,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "de",
|
||||
"about": "Über",
|
||||
"aboutThanks": "Vielen Dank an die folgenden Personen, die daran teilgenommen haben.\n",
|
||||
"acceptBeta": "Akzeptieren Sie Testversion-Updates",
|
||||
"add": "Neu",
|
||||
"addAServer": "Server hinzufügen",
|
||||
"addPrivateKey": "Private key hinzufügen",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.",
|
||||
"backupVersionNotMatch": "Die Backup-Version stimmt nicht überein.",
|
||||
"battery": "Batterie",
|
||||
"beforeConnect": "ServerBox wird nach der Verbindung ein Skript in `~/.config/server_box` schreiben und ausführen. Für weitere technische Details besuchen Sie bitte [Github]({url}).",
|
||||
"bgRun": "Hintergrundaktualisierung",
|
||||
"bgRunTip": "Dieser Schalter bedeutet nur, dass die App versuchen wird, im Hintergrund zu laufen. Ob sie im Hintergrund laufen kann, hängt davon ab, ob die Berechtigungen aktiviert sind oder nicht. Bei nativem Android deaktivieren Sie bitte \"Batterieoptimierung\" in dieser App, und bei miui ändern Sie bitte die Energiesparrichtlinie auf \"Unbegrenzt\".",
|
||||
"bioAuth": "Biozertifizierung",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Wenn das Terminal ein sicheres Tastenfeld öffnet, können Sie es aktivieren.",
|
||||
"collapseUI": "Zusammenbrechen",
|
||||
"collapseUITip": "Ob lange Listen in der Benutzeroberfläche standardmäßig eingeklappt werden sollen oder nicht",
|
||||
"collectUsage": "Nutzungsinformationen sammeln (unabhängig von der Privatsphäre).",
|
||||
"conn": "Verbindung",
|
||||
"connected": "in Verbindung gebracht",
|
||||
"container": "Container",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Export",
|
||||
"extraArgs": "Extra args",
|
||||
"failed": "Failed",
|
||||
"fdroidReleaseTip": "Wenn Sie diese App von Fdroid heruntergeladen haben, wird empfohlen, diese Option zu deaktivieren.",
|
||||
"feedback": "Feedback",
|
||||
"feedbackOnGithub": "Wenn du Fragen hast, stelle diese bitte auf Github.",
|
||||
"fieldMustNotEmpty": "Die Eingabefelder dürfen nicht leer sein.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "System verfolgen",
|
||||
"font": "Schriftarten",
|
||||
"fontSize": "Schriftgröße",
|
||||
"forExample": "Zum Beispiel",
|
||||
"force": "freiwillig",
|
||||
"foundNUpdate": "Update {count} gefunden",
|
||||
"fullScreen": "Vollbildmodus",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Images",
|
||||
"import": "Importieren",
|
||||
"inAppUpdate": "Im App aktualisieren? Andernfalls mit einem Browser herunterladen.",
|
||||
"init": "Initialisieren",
|
||||
"inner": "Eingebaut",
|
||||
"inputDomainHere": "Domain eingeben",
|
||||
"install": "install",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Auswahl merken",
|
||||
"rememberPwdInMem": "Passwort im Speicher behalten",
|
||||
"rememberPwdInMemTip": "Für Container, Aufhängen usw.",
|
||||
"rememberWindowSize": "Fenstergröße merken",
|
||||
"remotePath": "Entfernte Pfade",
|
||||
"rename": "Umbenennen",
|
||||
"reportBugsOnGithubIssue": "Bitte Bugs auf {url} melden",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "en",
|
||||
"about": "About",
|
||||
"aboutThanks": "Thanks to the following people who participated in.",
|
||||
"acceptBeta": "Accept test version updates",
|
||||
"add": "Add",
|
||||
"addAServer": "add a server",
|
||||
"addPrivateKey": "Add private key",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
|
||||
"backupVersionNotMatch": "Backup version is not match.",
|
||||
"battery": "Battery",
|
||||
"beforeConnect": "ServerBox will write and execute a script in `~/.config/server_box` after connection. For more technical details, please visit [Github]({url}).",
|
||||
"bgRun": "Run in backgroud",
|
||||
"bgRunTip": "This switch only means the program will try to run in the background, whether it can run in the background depends on whether the permission is enabled or not. For native Android, please disable \"Battery Optimization\" in this app, and for miui, please change the power saving policy to \"Unlimited\".",
|
||||
"bioAuth": "Biometric auth",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "If the terminal pops up a secure keyboard, you can enable it.",
|
||||
"collapseUI": "Collapse",
|
||||
"collapseUITip": "Whether to collapse long lists present in the UI by default",
|
||||
"collectUsage": "Collect usage information (unrelated to privacy).",
|
||||
"conn": "Connection",
|
||||
"connected": "Connected",
|
||||
"container": "Container",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Export",
|
||||
"extraArgs": "Extra args",
|
||||
"failed": "Failed",
|
||||
"fdroidReleaseTip": "If you downloaded this app from Fdroid, it is recommended to turn off this option.",
|
||||
"feedback": "Feedback",
|
||||
"feedbackOnGithub": "If you have any questions, please feedback on Github.",
|
||||
"fieldMustNotEmpty": "These fields must not be empty.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Follow system",
|
||||
"font": "Font",
|
||||
"fontSize": "Font size",
|
||||
"forExample": "For example",
|
||||
"force": "Force",
|
||||
"foundNUpdate": "Found {count} update",
|
||||
"fullScreen": "Full screen mode",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Images list",
|
||||
"import": "Import",
|
||||
"inAppUpdate": "Update within the app? Otherwise, download using a browser.",
|
||||
"init": "Initialize",
|
||||
"inner": "Inner",
|
||||
"inputDomainHere": "Input Domain here",
|
||||
"install": "install",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Remember the selection",
|
||||
"rememberPwdInMem": "Remember password in memory",
|
||||
"rememberPwdInMemTip": "Used for containers, suspending, etc.",
|
||||
"rememberWindowSize": "Remember window size",
|
||||
"remotePath": "Remote path",
|
||||
"rename": "Rename",
|
||||
"reportBugsOnGithubIssue": "Please report bugs on {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "es",
|
||||
"about": "Acerca de",
|
||||
"aboutThanks": "Gracias a los siguientes participantes.",
|
||||
"acceptBeta": "Aceptar actualizaciones de la versión de prueba",
|
||||
"add": "Añadir",
|
||||
"addAServer": "Agregar un servidor",
|
||||
"addPrivateKey": "Agregar una llave privada",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Los datos exportados solo están encriptados de manera básica, por favor guárdalos en un lugar seguro.",
|
||||
"backupVersionNotMatch": "La versión de la copia de seguridad no coincide, no se puede restaurar",
|
||||
"battery": "Batería",
|
||||
"beforeConnect": "ServerBox escribirá y ejecutará un script en `~/.config/server_box` después de la conexión. Para más detalles técnicos, por favor visite [Github]({url}).",
|
||||
"bgRun": "Ejecución en segundo plano",
|
||||
"bgRunTip": "Este interruptor solo indica que la aplicación intentará correr en segundo plano, si puede hacerlo o no depende de si tiene el permiso correspondiente. En Android puro, por favor desactiva la “optimización de batería” para esta app, en MIUI por favor cambia la estrategia de ahorro de energía a “Sin restricciones”.",
|
||||
"bioAuth": "Autenticación biométrica",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Si el terminal muestra un teclado seguro, puedes activarlo.",
|
||||
"collapseUI": "Colapsar",
|
||||
"collapseUITip": "¿Colapsar por defecto las listas largas en la UI?",
|
||||
"collectUsage": "Recopilar información de uso (no relacionada con la privacidad).",
|
||||
"conn": "Conectar",
|
||||
"connected": "Conectado",
|
||||
"container": "Contenedor",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Exportar",
|
||||
"extraArgs": "Argumentos extra",
|
||||
"failed": "Fallido",
|
||||
"fdroidReleaseTip": "Si descargaste esta aplicación desde Fdroid, se recomienda desactivar esta opción.",
|
||||
"feedback": "Retroalimentación",
|
||||
"feedbackOnGithub": "Si tienes algún problema, por favor informa en GitHub",
|
||||
"fieldMustNotEmpty": "Estos campos no pueden estar vacíos.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Seguir al sistema",
|
||||
"font": "Fuente",
|
||||
"fontSize": "Tamaño de fuente",
|
||||
"forExample": "Por ejemplo",
|
||||
"force": "Forzar",
|
||||
"foundNUpdate": "Encontradas {count} actualizaciones",
|
||||
"fullScreen": "Modo pantalla completa",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Lista de imágenes",
|
||||
"import": "Importar",
|
||||
"inAppUpdate": "¿Actualizar dentro de la app? De lo contrario, descargar usando un navegador.",
|
||||
"init": "Inicializar",
|
||||
"inner": "Interno",
|
||||
"inputDomainHere": "Introduce el dominio aquí",
|
||||
"install": "Instalar",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Recordar la selección",
|
||||
"rememberPwdInMem": "Recordar contraseña en la memoria",
|
||||
"rememberPwdInMemTip": "Utilizado para contenedores, suspensión, etc.",
|
||||
"rememberWindowSize": "Recordar el tamaño de la ventana",
|
||||
"remotePath": "Ruta remota",
|
||||
"rename": "Renombrar",
|
||||
"reportBugsOnGithubIssue": "Por favor, informa los problemas en {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "fr",
|
||||
"about": "À propos",
|
||||
"aboutThanks": "Merci aux personnes suivantes qui ont participé.",
|
||||
"acceptBeta": "Accepter les mises à jour de la version de test",
|
||||
"add": "Ajouter",
|
||||
"addAServer": "Ajouter un serveur",
|
||||
"addPrivateKey": "Ajouter une clé privée",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Les données exportées sont simplement chiffrées. \nVeuillez les garder en sécurité.",
|
||||
"backupVersionNotMatch": "La version de sauvegarde ne correspond pas.",
|
||||
"battery": "Batterie",
|
||||
"beforeConnect": "ServerBox écrira et exécutera un script dans `~/.config/server_box` après la connexion. Pour plus de détails techniques, veuillez visiter [Github]({url}).",
|
||||
"bgRun": "Exécution en arrière-plan",
|
||||
"bgRunTip": "Cette option signifie seulement que le programme essaiera de s'exécuter en arrière-plan, que cela soit possible dépend de l'autorisation activée ou non. Pour Android natif, veuillez désactiver l'« Optimisation de la batterie » dans cette application, et pour MIUI, veuillez changer la politique d'économie d'énergie en « Illimité ».",
|
||||
"bioAuth": "Authentification biométrique",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Si le terminal affiche un clavier sécurisé, vous pouvez l'activer.",
|
||||
"collapseUI": "Réduire",
|
||||
"collapseUITip": "Indique si les longues listes présentées dans l'interface utilisateur doivent être réduites par défaut.",
|
||||
"collectUsage": "Collecter des informations d'utilisation (sans rapport avec la confidentialité).",
|
||||
"conn": "Connexion",
|
||||
"connected": "Connecté",
|
||||
"container": "Conteneur",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Exporter",
|
||||
"extraArgs": "Arguments supplémentaires",
|
||||
"failed": "Échoué",
|
||||
"fdroidReleaseTip": "Si vous avez téléchargé cette application depuis Fdroid, il est recommandé de désactiver cette option.",
|
||||
"feedback": "Retour",
|
||||
"feedbackOnGithub": "Si vous avez des questions, veuillez donner votre avis sur Github.",
|
||||
"fieldMustNotEmpty": "Ces champs ne doivent pas être vides.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Suivre le système",
|
||||
"font": "Police",
|
||||
"fontSize": "Taille de la police",
|
||||
"forExample": "Par exemple",
|
||||
"force": "Forcer",
|
||||
"foundNUpdate": "{count} mise à jour trouvée",
|
||||
"fullScreen": "Mode plein écran",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Liste des images",
|
||||
"import": "Importer",
|
||||
"inAppUpdate": "Mettre à jour dans l'application ? Sinon, téléchargez en utilisant un navigateur.",
|
||||
"init": "Initialiser",
|
||||
"inner": "Interne",
|
||||
"inputDomainHere": "Saisissez le domaine ici",
|
||||
"install": "Installer",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Se souvenir du choix",
|
||||
"rememberPwdInMem": "Mémoriser le mot de passe en mémoire",
|
||||
"rememberPwdInMemTip": "Utilisé pour les conteneurs, la suspension, etc.",
|
||||
"rememberWindowSize": "Se souvenir de la taille de la fenêtre",
|
||||
"remotePath": "Chemin distant",
|
||||
"rename": "Renommer",
|
||||
"reportBugsOnGithubIssue": "Veuillez signaler les bugs sur {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "id",
|
||||
"about": "Tentang",
|
||||
"aboutThanks": "Terima kasih kepada orang -orang berikut yang berpartisipasi.",
|
||||
"acceptBeta": "Terima pembaruan versi uji coba",
|
||||
"add": "Menambahkan",
|
||||
"addAServer": "tambahkan server",
|
||||
"addPrivateKey": "Tambahkan kunci pribadi",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.",
|
||||
"backupVersionNotMatch": "Versi cadangan tidak cocok.",
|
||||
"battery": "Baterai",
|
||||
"beforeConnect": "ServerBox akan menulis dan menjalankan skrip di `~/.config/server_box` setelah koneksi. Untuk detail teknis lebih lanjut, silakan kunjungi [Github]({url}).",
|
||||
"bgRun": "Jalankan di Backgroud",
|
||||
"bgRunTip": "Sakelar ini hanya berarti aplikasi akan mencoba berjalan di latar belakang, apakah aplikasi dapat berjalan di latar belakang tergantung pada apakah izin diaktifkan atau tidak. Untuk Android asli, nonaktifkan \"Pengoptimalan Baterai\" di aplikasi ini, dan untuk miui, ubah kebijakan penghematan daya ke \"Tidak Terbatas\".",
|
||||
"bioAuth": "Biosertifikasi",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Jika terminal munculkan keyboard aman, Anda bisa mengaktifkannya.",
|
||||
"collapseUI": "Runtuh",
|
||||
"collapseUITip": "Apakah akan menciutkan daftar panjang yang ada di UI secara default atau tidak",
|
||||
"collectUsage": "Mengumpulkan informasi penggunaan (tidak terkait dengan privasi).",
|
||||
"conn": "Koneksi",
|
||||
"connected": "Terhubung",
|
||||
"container": "Wadah",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Ekspor",
|
||||
"extraArgs": "Args ekstra",
|
||||
"failed": "Gagal",
|
||||
"fdroidReleaseTip": "Jika Anda mengunduh aplikasi ini dari Fdroid, disarankan untuk mematikan opsi ini.",
|
||||
"feedback": "Masukan",
|
||||
"feedbackOnGithub": "Jika Anda memiliki pertanyaan, silakan umpan balik tentang GitHub.",
|
||||
"fieldMustNotEmpty": "Bidang -bidang ini tidak boleh kosong.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Ikuti sistem",
|
||||
"font": "Font",
|
||||
"fontSize": "Ukuran huruf",
|
||||
"forExample": "Sebagai contoh",
|
||||
"force": "sukarela",
|
||||
"foundNUpdate": "Menemukan {count} pembaruan",
|
||||
"fullScreen": "Mode Layar Penuh",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Daftar gambar",
|
||||
"import": "Impor",
|
||||
"inAppUpdate": "Perbarui di dalam aplikasi? Jika tidak, unduh menggunakan browser.",
|
||||
"init": "Menginisialisasi",
|
||||
"inner": "Batin",
|
||||
"inputDomainHere": "Input domain di sini",
|
||||
"install": "Install",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Ingat pilihan",
|
||||
"rememberPwdInMem": "Ingat kata sandi di dalam memori",
|
||||
"rememberPwdInMemTip": "Digunakan untuk kontainer, menangguhkan, dll.",
|
||||
"rememberWindowSize": "Ingat ukuran jendela",
|
||||
"remotePath": "Jalur jarak jauh",
|
||||
"rename": "Ganti nama",
|
||||
"reportBugsOnGithubIssue": "Harap laporkan bug di {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "ja",
|
||||
"about": "約",
|
||||
"aboutThanks": "以下の参加者に感謝します。",
|
||||
"acceptBeta": "テストバージョンの更新を受け入れる",
|
||||
"add": "追加",
|
||||
"addAServer": "サーバーを追加する",
|
||||
"addPrivateKey": "プライベートキーを追加",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "エクスポートされたデータは簡単に暗号化されています。適切に保管してください。",
|
||||
"backupVersionNotMatch": "バックアップバージョンが一致しないため、復元できません",
|
||||
"battery": "バッテリー",
|
||||
"beforeConnect": "ServerBoxは接続後に`~/.config/server_box`にスクリプトを書き込み実行します。詳細な技術情報については[Github]({url})をご覧ください。",
|
||||
"bgRun": "バックグラウンド実行",
|
||||
"bgRunTip": "このスイッチはプログラムがバックグラウンドで実行を試みることを意味しますが、実際にバックグラウンドで実行できるかどうかは、権限が有効になっているかに依存します。ネイティブAndroidでは、このアプリの「バッテリー最適化」をオフにしてください。MIUIでは、省エネモードを「無制限」に変更してください。",
|
||||
"bioAuth": "生体認証",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "ターミナルがセキュアキーボードを表示した場合、それを有効にできます。",
|
||||
"collapseUI": "UIを折りたたむ",
|
||||
"collapseUITip": "UIの長いリストをデフォルトで折りたたむかどうか",
|
||||
"collectUsage": "使用情報を収集する(プライバシーとは関係ない)。",
|
||||
"conn": "接続",
|
||||
"connected": "接続済み",
|
||||
"container": "コンテナ",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "エクスポート",
|
||||
"extraArgs": "追加引数",
|
||||
"failed": "失敗しました",
|
||||
"fdroidReleaseTip": "このアプリをFdroidからダウンロードした場合、このオプションをオフにすることをお勧めします。",
|
||||
"feedback": "フィードバック",
|
||||
"feedbackOnGithub": "問題がある場合は、GitHubでフィードバックしてください",
|
||||
"fieldMustNotEmpty": "これらの入力フィールドは空にできません。",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "システムに従う",
|
||||
"font": "フォント",
|
||||
"fontSize": "フォントサイズ",
|
||||
"forExample": "例えば",
|
||||
"force": "強制",
|
||||
"foundNUpdate": "{count}個の更新が見つかりました",
|
||||
"fullScreen": "フルスクリーンモード",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "イメージリスト",
|
||||
"import": "インポート",
|
||||
"inAppUpdate": "アプリ内で更新しますか?それ以外の場合は、ブラウザを使用してダウンロードしてください。",
|
||||
"init": "初期化する",
|
||||
"inner": "内蔵",
|
||||
"inputDomainHere": "ここにドメインを入力",
|
||||
"install": "インストール",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "選択を記憶する",
|
||||
"rememberPwdInMem": "メモリにパスワードを記憶する",
|
||||
"rememberPwdInMemTip": "コンテナ、一時停止などに使用されます。",
|
||||
"rememberWindowSize": "ウィンドウサイズを記憶する",
|
||||
"remotePath": "リモートパス",
|
||||
"rename": "名前を変更",
|
||||
"reportBugsOnGithubIssue": "{url}で問題を報告してください",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "nl",
|
||||
"about": "Over",
|
||||
"aboutThanks": "Met dank aan de volgende mensen die hebben deelgenomen aan.",
|
||||
"acceptBeta": "Accepteer testversie-updates",
|
||||
"add": "Toevoegen",
|
||||
"addAServer": "een server toevoegen",
|
||||
"addPrivateKey": "Privésleutel toevoegen",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "De geëxporteerde gegevens zijn simpelweg versleuteld. \nBewaar deze aub veilig.",
|
||||
"backupVersionNotMatch": "Back-upversie komt niet overeen.",
|
||||
"battery": "Batterij",
|
||||
"beforeConnect": "ServerBox zal na verbinding een script schrijven en uitvoeren in `~/.config/server_box`. Voor meer technische details, bezoek [Github]({url}).",
|
||||
"bgRun": "Uitvoeren op de achtergrond",
|
||||
"bgRunTip": "Deze schakelaar betekent alleen dat het programma zal proberen op de achtergrond uit te voeren, of het in de achtergrond kan worden uitgevoerd, hangt af van of de toestemming is ingeschakeld of niet. Voor native Android, schakel \"Batterijoptimalisatie\" uit in deze app, en voor miui, wijzig de energiebesparingsbeleid naar \"Onbeperkt\".",
|
||||
"bioAuth": "Biometrische authenticatie",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Als de terminal een beveiligd toetsenbord weergeeft, kunt u dit inschakelen.",
|
||||
"collapseUI": "Inklappen",
|
||||
"collapseUITip": "Of lange lijsten in de UI standaard moeten worden ingeklapt",
|
||||
"collectUsage": "Gebruiksinformatie verzamelen (niet gerelateerd aan privacy).",
|
||||
"conn": "Verbinding",
|
||||
"connected": "Verbonden",
|
||||
"container": "Container",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Exporteren",
|
||||
"extraArgs": "Extra argumenten",
|
||||
"failed": "Mislukt",
|
||||
"fdroidReleaseTip": "Als u deze app van Fdroid heeft gedownload, wordt aanbevolen deze optie uit te schakelen.",
|
||||
"feedback": "Feedback",
|
||||
"feedbackOnGithub": "Als je vragen hebt, geef dan feedback op Github.",
|
||||
"fieldMustNotEmpty": "Deze velden mogen niet leeg zijn.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Volg systeem",
|
||||
"font": "Lettertype",
|
||||
"fontSize": "Lettergrootte",
|
||||
"forExample": "Bijvoorbeeld",
|
||||
"force": "Forceer",
|
||||
"foundNUpdate": "{count} update gevonden",
|
||||
"fullScreen": "Volledig schermmodus",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Lijst met afbeeldingen",
|
||||
"import": "Importeren",
|
||||
"inAppUpdate": "Bijwerken binnen de app? Anders downloaden via een browser.",
|
||||
"init": "Initialiseren",
|
||||
"inner": "Intern",
|
||||
"inputDomainHere": "Voer hier domein in",
|
||||
"install": "Installeren",
|
||||
@@ -176,6 +180,7 @@
|
||||
"newContainer": "Nieuwe container",
|
||||
"noClient": "Geen client",
|
||||
"noInterface": "Geen interface",
|
||||
"noLineChart": "lijndiagrammen gebruiken",
|
||||
"noNotiPerm": "Geen meldingsmachtigingen, mogelijk geen voortgangsindicatie bij het downloaden van app-updates.",
|
||||
"noOptions": "Geen opties",
|
||||
"noPrivateKeyTip": "De privésleutel bestaat niet, deze is mogelijk verwijderd of er is een configuratiefout.",
|
||||
@@ -228,6 +233,7 @@
|
||||
"rememberChoice": "Selectie onthouden",
|
||||
"rememberPwdInMem": "Wachtwoord onthouden in geheugen",
|
||||
"rememberPwdInMemTip": "Gebruikt voor containers, opschorting, enz.",
|
||||
"rememberWindowSize": "Venstergrootte onthouden",
|
||||
"remotePath": "Extern pad",
|
||||
"rename": "Hernoemen",
|
||||
"reportBugsOnGithubIssue": "Meld alstublieft bugs op {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "pt",
|
||||
"about": "Sobre",
|
||||
"aboutThanks": "Agradecimentos a todos os participantes.",
|
||||
"acceptBeta": "Aceitar atualizações da versão de teste",
|
||||
"add": "Adicionar",
|
||||
"addAServer": "Adicionar um servidor",
|
||||
"addPrivateKey": "Adicionar uma chave privada",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Os dados exportados são criptografados de forma simples, por favor, guarde-os com segurança.",
|
||||
"backupVersionNotMatch": "Versão de backup não compatível, não é possível restaurar",
|
||||
"battery": "Bateria",
|
||||
"beforeConnect": "O ServerBox escreverá e executará um script em `~/.config/server_box` após a conexão. Para mais detalhes técnicos, por favor visite [Github]({url}).",
|
||||
"bgRun": "Execução em segundo plano",
|
||||
"bgRunTip": "Este interruptor indica que o programa tentará rodar em segundo plano, mas a capacidade de fazer isso depende das permissões concedidas. No Android nativo, desative a 'Otimização de bateria' para este app, no MIUI, altere a estratégia de economia de energia para 'Sem restrições'.",
|
||||
"bioAuth": "Autenticação biométrica",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Se o terminal abrir um teclado seguro, você pode ativá-lo.",
|
||||
"collapseUI": "Colapsar",
|
||||
"collapseUITip": "Deve colapsar listas longas na UI por padrão?",
|
||||
"collectUsage": "Coletar informações de uso (não relacionadas à privacidade).",
|
||||
"conn": "Conectar",
|
||||
"connected": "Conectado",
|
||||
"container": "Contêiner",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "Exportar",
|
||||
"extraArgs": "Argumentos extras",
|
||||
"failed": "Falhou",
|
||||
"fdroidReleaseTip": "Se você baixou este aplicativo do Fdroid, é recomendado desativar esta opção.",
|
||||
"feedback": "Feedback",
|
||||
"feedbackOnGithub": "Se você tem qualquer problema, por favor, dê feedback no GitHub",
|
||||
"fieldMustNotEmpty": "Estes campos não podem estar vazios.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "Seguir sistema",
|
||||
"font": "Fonte",
|
||||
"fontSize": "Tamanho da fonte",
|
||||
"forExample": "Por exemplo",
|
||||
"force": "Forçar",
|
||||
"foundNUpdate": "Encontradas {count} atualizações",
|
||||
"fullScreen": "Modo tela cheia",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "Lista de imagens",
|
||||
"import": "Importar",
|
||||
"inAppUpdate": "Atualizar dentro do app? Caso contrário, baixe usando um navegador.",
|
||||
"init": "Inicializar",
|
||||
"inner": "Interno",
|
||||
"inputDomainHere": "Insira o domínio aqui",
|
||||
"install": "Instalar",
|
||||
@@ -176,7 +180,7 @@
|
||||
"newContainer": "Novo contêiner",
|
||||
"noClient": "Sem conexão SSH",
|
||||
"noInterface": "Sem interface disponível",
|
||||
"noLineChart": "Gebruik geen lijndiagrammen",
|
||||
"noLineChart": "Não usar gráficos de linha",
|
||||
"noNotiPerm": "Sem permissão de notificação, possivelmente sem indicação de progresso ao baixar atualizações de aplicativos.",
|
||||
"noOptions": "Sem opções",
|
||||
"noPrivateKeyTip": "A chave privada não existe, pode ter sido deletada ou há um erro de configuração.",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Lembrar da seleção",
|
||||
"rememberPwdInMem": "Lembrar senha na memória",
|
||||
"rememberPwdInMemTip": "Usado para contêineres, suspensão, etc.",
|
||||
"rememberWindowSize": "Lembrar o tamanho da janela",
|
||||
"remotePath": "Caminho remoto",
|
||||
"rename": "Renomear",
|
||||
"reportBugsOnGithubIssue": "Por favor, reporte problemas em {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "ru",
|
||||
"about": "о",
|
||||
"aboutThanks": "Благодарности всем участникам.",
|
||||
"acceptBeta": "Принять обновления тестовой версии",
|
||||
"add": "добавить",
|
||||
"addAServer": "добавить сервер",
|
||||
"addPrivateKey": "добавить приватный ключ",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "Экспортированные данные зашифрованы простым способом, пожалуйста, храните их в безопасности.",
|
||||
"backupVersionNotMatch": "Версия резервной копии не совпадает, восстановление невозможно",
|
||||
"battery": "батарея",
|
||||
"beforeConnect": "ServerBox запишет и выполнит скрипт в `~/.config/server_box` после подключения. Для получения дополнительных технических подробностей, пожалуйста, посетите [Github]({url}).",
|
||||
"bgRun": "работа в фоновом режиме",
|
||||
"bgRunTip": "Этот переключатель означает, что программа будет пытаться работать в фоновом режиме, но фактическое выполнение зависит от того, включено ли разрешение. Для нативного Android отключите «Оптимизацию батареи» для этого приложения, для MIUI измените стратегию энергосбережения на «Без ограничений».",
|
||||
"bioAuth": "биометрическая аутентификация",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "Если терминал отображает безопасную клавиатуру, вы можете ее активировать.",
|
||||
"collapseUI": "свернуть",
|
||||
"collapseUITip": "Свернуть длинные списки в UI по умолчанию",
|
||||
"collectUsage": "Сбор информации об использовании (не связано с конфиденциальностью).",
|
||||
"conn": "подключение",
|
||||
"connected": "подключено",
|
||||
"container": "контейнер",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "экспорт",
|
||||
"extraArgs": "дополнительные аргументы",
|
||||
"failed": "неудача",
|
||||
"fdroidReleaseTip": "Если вы скачали это приложение с Fdroid, рекомендуется отключить эту опцию.",
|
||||
"feedback": "обратная связь",
|
||||
"feedbackOnGithub": "Если у вас есть какие-либо вопросы, пожалуйста, отправьте отзыв на GitHub",
|
||||
"fieldMustNotEmpty": "Эти поля не могут быть пустыми.",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "следовать за системой",
|
||||
"font": "шрифт",
|
||||
"fontSize": "размер шрифта",
|
||||
"forExample": "Например",
|
||||
"force": "принудительно",
|
||||
"foundNUpdate": "Найдено {count} обновлений",
|
||||
"fullScreen": "полноэкранный режим",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "список образов",
|
||||
"import": "импорт",
|
||||
"inAppUpdate": "Обновить в приложении? В противном случае загрузите с помощью браузера.",
|
||||
"init": "Инициализировать",
|
||||
"inner": "встроенный",
|
||||
"inputDomainHere": "введите домен здесь",
|
||||
"install": "установить",
|
||||
@@ -176,7 +180,7 @@
|
||||
"newContainer": "создать контейнер",
|
||||
"noClient": "нет SSH соединения",
|
||||
"noInterface": "нет доступных интерфейсов",
|
||||
"noLineChart": "Não use gráficos de linha",
|
||||
"noLineChart": "Не использовать линейные графики",
|
||||
"noNotiPerm": "Нет разрешения на уведомления, возможно отсутствие индикации прогресса при загрузке обновлений приложений.",
|
||||
"noOptions": "нет доступных опций",
|
||||
"noPrivateKeyTip": "Приватный ключ не существует, возможно, он был удален или есть ошибка в настройках.",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "Запомнить выбор",
|
||||
"rememberPwdInMem": "Запомнить пароль в памяти",
|
||||
"rememberPwdInMemTip": "Используется для контейнеров, приостановки и т. д.",
|
||||
"rememberWindowSize": "Запомнить размер окна",
|
||||
"remotePath": "удаленный путь",
|
||||
"rename": "переименовать",
|
||||
"reportBugsOnGithubIssue": "Пожалуйста, сообщайте о проблемах на {url}",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "zh",
|
||||
"about": "关于",
|
||||
"aboutThanks": "感谢以下参与的各位。",
|
||||
"acceptBeta": "接受测试版更新推送",
|
||||
"add": "新增",
|
||||
"addAServer": "添加服务器",
|
||||
"addPrivateKey": "添加一个私钥",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
|
||||
"backupVersionNotMatch": "备份版本不匹配,无法恢复",
|
||||
"battery": "电池",
|
||||
"beforeConnect": "ServerBox 将在连接后,在 `~/.config/server_box` 写入脚本并执行,更多的技术细节请访问 [Github]({url})。",
|
||||
"bgRun": "后台运行",
|
||||
"bgRunTip": "此开关只代表程序会尝试在后台运行,具体能否后台运行取决于是否开启了权限。原生 Android 请关闭本 App 的“电池优化”,MIUI 请修改省电策略为“无限制”。",
|
||||
"bioAuth": "生物认证",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "如果终端弹出安全键盘,可以开启",
|
||||
"collapseUI": "折叠",
|
||||
"collapseUITip": "是否默认折叠UI中存在的长列表",
|
||||
"collectUsage": "搜集使用信息(与隐私无关)",
|
||||
"conn": "连接",
|
||||
"connected": "已连接",
|
||||
"container": "容器",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "导出",
|
||||
"extraArgs": "额外参数",
|
||||
"failed": "失败",
|
||||
"fdroidReleaseTip": "如果你是从 Fdroid 下载的本应用,推荐关闭此选项",
|
||||
"feedback": "反馈",
|
||||
"feedbackOnGithub": "如果你有任何问题,请在GitHub反馈",
|
||||
"fieldMustNotEmpty": "这些输入框不能为空。",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "跟随系统",
|
||||
"font": "字体",
|
||||
"fontSize": "字体大小",
|
||||
"forExample": "例如",
|
||||
"force": "强制",
|
||||
"foundNUpdate": "找到 {count} 个更新",
|
||||
"fullScreen": "全屏模式",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "镜像列表",
|
||||
"import": "导入",
|
||||
"inAppUpdate": "在App内更新?否则使用浏览器下载",
|
||||
"init": "初始化",
|
||||
"inner": "内置",
|
||||
"inputDomainHere": "在这里输入域名",
|
||||
"install": "安装",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "记住选择",
|
||||
"rememberPwdInMem": "在内存中记住密码",
|
||||
"rememberPwdInMemTip": "用于容器、挂起等",
|
||||
"rememberWindowSize": "记住窗口大小",
|
||||
"remotePath": "远端路径",
|
||||
"rename": "重命名",
|
||||
"reportBugsOnGithubIssue": "请到 {url} 提交问题",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"@@locale": "zh_TW",
|
||||
"about": "關於",
|
||||
"aboutThanks": "感謝以下參與的各位。",
|
||||
"acceptBeta": "接受測試版更新推送",
|
||||
"add": "新增",
|
||||
"addAServer": "新增服務器",
|
||||
"addPrivateKey": "新增一個私鑰",
|
||||
@@ -25,6 +26,7 @@
|
||||
"backupTip": "導出的數據僅進行了簡單加密,請妥善保管。",
|
||||
"backupVersionNotMatch": "備份版本不匹配,無法還原",
|
||||
"battery": "電池",
|
||||
"beforeConnect": "ServerBox將在連接後,在`~/.config/server_box`寫入腳本並執行,更多的技術細節請訪問[Github]({url})。",
|
||||
"bgRun": "背景運行",
|
||||
"bgRunTip": "此開關只代表程式會嘗試在背景執行,具體能否背景運行取決於是否開啟了權限。 原生 Android 請關閉本 App 的“電池優化”,MIUI 請修改省電策略為“無限制”。",
|
||||
"bioAuth": "生物認證",
|
||||
@@ -44,7 +46,6 @@
|
||||
"cnKeyboardCompTip": "如果終端彈出安全鍵盤,您可以啟用它。",
|
||||
"collapseUI": "折疊",
|
||||
"collapseUITip": "是否預設折疊UI中存在的長列表",
|
||||
"collectUsage": "搜集使用信息(與隱私無關)",
|
||||
"conn": "連接",
|
||||
"connected": "已連接",
|
||||
"container": "容器",
|
||||
@@ -100,6 +101,7 @@
|
||||
"export": "導出",
|
||||
"extraArgs": "額外參數",
|
||||
"failed": "失敗",
|
||||
"fdroidReleaseTip": "如果你是從 Fdroid 下載的本應用,推薦關閉此選項",
|
||||
"feedback": "反饋",
|
||||
"feedbackOnGithub": "如果你有任何問題,請在GitHub反饋",
|
||||
"fieldMustNotEmpty": "這些輸入框不能為空。",
|
||||
@@ -110,6 +112,7 @@
|
||||
"followSystem": "跟隨系統",
|
||||
"font": "字體",
|
||||
"fontSize": "字體大小",
|
||||
"forExample": "例如",
|
||||
"force": "強制",
|
||||
"foundNUpdate": "找到 {count} 個更新",
|
||||
"fullScreen": "全屏模式",
|
||||
@@ -133,6 +136,7 @@
|
||||
"imagesList": "鏡像列表",
|
||||
"import": "導入",
|
||||
"inAppUpdate": "在App內更新?否則使用瀏覽器下載。",
|
||||
"init": "初始化",
|
||||
"inner": "內置",
|
||||
"inputDomainHere": "在這裡輸入域名",
|
||||
"install": "安裝",
|
||||
@@ -229,6 +233,7 @@
|
||||
"rememberChoice": "記住選擇",
|
||||
"rememberPwdInMem": "在記憶體中記住密碼",
|
||||
"rememberPwdInMemTip": "用於容器、暫停等",
|
||||
"rememberWindowSize": "記住窗口大小",
|
||||
"remotePath": "遠端路徑",
|
||||
"rename": "重命名",
|
||||
"reportBugsOnGithubIssue": "請到 {url} 提交問題",
|
||||
|
||||
@@ -10,22 +10,22 @@ import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:toolbox/app.dart';
|
||||
import 'package:toolbox/core/utils/sync/icloud.dart';
|
||||
import 'package:toolbox/core/utils/sync/webdav.dart';
|
||||
import 'package:toolbox/data/model/app/menu/server_func.dart';
|
||||
import 'package:toolbox/data/model/app/net_view.dart';
|
||||
import 'package:toolbox/data/model/app/server_detail_card.dart';
|
||||
import 'package:toolbox/data/model/server/custom.dart';
|
||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/model/server/snippet.dart';
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
import 'package:toolbox/data/res/build_data.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/provider.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:server_box/app.dart';
|
||||
import 'package:server_box/core/utils/sync/icloud.dart';
|
||||
import 'package:server_box/core/utils/sync/webdav.dart';
|
||||
import 'package:server_box/data/model/app/menu/server_func.dart';
|
||||
import 'package:server_box/data/model/app/net_view.dart';
|
||||
import 'package:server_box/data/model/app/server_detail_card.dart';
|
||||
import 'package:server_box/data/model/server/custom.dart';
|
||||
import 'package:server_box/data/model/server/private_key_info.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/model/server/wol_cfg.dart';
|
||||
import 'package:server_box/data/model/ssh/virtual_key.dart';
|
||||
import 'package:server_box/data/res/build_data.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/provider.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
_runInZone(() async {
|
||||
@@ -55,7 +55,6 @@ void _runInZone(void Function() body) {
|
||||
runZonedGuarded(
|
||||
body,
|
||||
(obj, trace) {
|
||||
Analysis.recordException(trace);
|
||||
Loggers.root.warning(obj, null, trace);
|
||||
},
|
||||
zoneSpecification: zoneSpec,
|
||||
@@ -69,7 +68,13 @@ Future<void> _initApp() async {
|
||||
await _initData();
|
||||
_setupDebug();
|
||||
|
||||
SystemUIs.initDesktopWindow(Stores.setting.hideTitleBar.fetch());
|
||||
final windowSize = Stores.setting.windowSize;
|
||||
final hideTitleBar = Stores.setting.hideTitleBar.fetch();
|
||||
SystemUIs.initDesktopWindow(
|
||||
hideTitleBar: hideTitleBar,
|
||||
size: windowSize.fetch().toSize(),
|
||||
listener: WindowSizeListener(windowSize),
|
||||
);
|
||||
FontUtils.loadFrom(Stores.setting.fontPath.fetch());
|
||||
|
||||
_doPlatformRelated();
|
||||
@@ -87,6 +92,7 @@ Future<void> _initData() async {
|
||||
Hive.registerAdapter(NetViewTypeAdapter()); // 5
|
||||
Hive.registerAdapter(ServerFuncBtnAdapter()); // 6
|
||||
Hive.registerAdapter(ServerCustomAdapter()); // 7
|
||||
Hive.registerAdapter(WakeOnLanCfgAdapter()); // 8
|
||||
|
||||
await Stores.setting.init();
|
||||
await Stores.server.init();
|
||||
@@ -98,6 +104,8 @@ Future<void> _initData() async {
|
||||
Pros.snippet.load();
|
||||
Pros.key.load();
|
||||
await Pros.app.init();
|
||||
|
||||
if (Stores.setting.betaTest.fetch()) AppUpdate.chan = AppUpdateChan.beta;
|
||||
}
|
||||
|
||||
void _setupDebug() {
|
||||
@@ -108,10 +116,6 @@ void _setupDebug() {
|
||||
if (record.error != null) print(record.error);
|
||||
if (record.stackTrace != null) print(record.stackTrace);
|
||||
});
|
||||
|
||||
if (Stores.setting.collectUsage.fetch()) {
|
||||
Analysis.init(Urls.analysis, '0772e65c696709f879d87db77ae1a811259e3eb9');
|
||||
}
|
||||
}
|
||||
|
||||
void _doPlatformRelated() async {
|
||||
|
||||
@@ -5,14 +5,14 @@ import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/core/utils/sync/icloud.dart';
|
||||
import 'package:toolbox/core/utils/sync/webdav.dart';
|
||||
import 'package:toolbox/data/model/app/backup.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/utils/sync/icloud.dart';
|
||||
import 'package:server_box/core/utils/sync/webdav.dart';
|
||||
import 'package:server_box/data/model/app/backup.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/res/misc.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
import 'package:server_box/data/res/url.dart';
|
||||
|
||||
class BackupPage extends StatelessWidget {
|
||||
BackupPage({super.key});
|
||||
@@ -66,18 +66,7 @@ class BackupPage extends StatelessWidget {
|
||||
trailing: const Icon(Icons.save),
|
||||
onTap: () async {
|
||||
final path = await Backup.backup();
|
||||
debugPrint("Backup path: $path");
|
||||
|
||||
/// Issue #188
|
||||
switch (Pfs.type) {
|
||||
case Pfs.windows:
|
||||
final backslashPath = path.replaceAll('/', '\\');
|
||||
await Process.run('explorer', ['/select,$backslashPath']);
|
||||
case Pfs.linux:
|
||||
await Process.run('xdg-open', [path]);
|
||||
default:
|
||||
await Pfs.sharePath(path);
|
||||
}
|
||||
await Pfs.share(path: path);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
|
||||
@@ -3,13 +3,13 @@ import 'dart:async';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/data/model/app/menu/base.dart';
|
||||
import 'package:toolbox/data/model/app/menu/container.dart';
|
||||
import 'package:toolbox/data/model/container/image.dart';
|
||||
import 'package:toolbox/data/model/container/type.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/route.dart';
|
||||
import 'package:server_box/data/model/app/menu/base.dart';
|
||||
import 'package:server_box/data/model/app/menu/container.dart';
|
||||
import 'package:server_box/data/model/container/image.dart';
|
||||
import 'package:server_box/data/model/container/type.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import '../../data/model/container/ps.dart';
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
@@ -206,7 +206,10 @@ class _ContainerPageState extends State<ContainerPage> {
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'${item.image ?? l10n.unknown} - ${item.running ? l10n.running : l10n.stopped}',
|
||||
'${item.image ?? l10n.unknown} - ${switch (item) {
|
||||
final PodmanPs ps => ps.running ? l10n.running : l10n.stopped,
|
||||
final DockerPs ps => ps.state,
|
||||
}}',
|
||||
style: UIs.text13Grey,
|
||||
),
|
||||
_buildPsItemStats(item),
|
||||
@@ -550,13 +553,19 @@ class _ContainerPageState extends State<ContainerPage> {
|
||||
case ContainerMenu.logs:
|
||||
AppRoutes.ssh(
|
||||
spi: widget.spi,
|
||||
initCmd: 'docker logs -f --tail 100 ${dItem.id}',
|
||||
initCmd: '${switch (_container.type) {
|
||||
ContainerType.podman => 'podman',
|
||||
ContainerType.docker => 'docker',
|
||||
}} logs -f --tail 100 ${dItem.id}',
|
||||
).go(context);
|
||||
break;
|
||||
case ContainerMenu.terminal:
|
||||
AppRoutes.ssh(
|
||||
spi: widget.spi,
|
||||
initCmd: 'docker exec -it ${dItem.id} sh',
|
||||
initCmd: '${switch (_container.type) {
|
||||
ContainerType.podman => 'podman',
|
||||
ContainerType.docker => 'docker',
|
||||
}} exec -it ${dItem.id} sh',
|
||||
).go(context);
|
||||
break;
|
||||
// case DockerMenuType.stats:
|
||||
|
||||
@@ -8,9 +8,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_highlight/theme_map.dart';
|
||||
import 'package:flutter_highlight/themes/a11y-light.dart';
|
||||
import 'package:flutter_highlight/themes/monokai.dart';
|
||||
import 'package:toolbox/core/extension/context/locale.dart';
|
||||
import 'package:toolbox/data/res/highlight.dart';
|
||||
import 'package:toolbox/data/res/store.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/res/highlight.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
import '../widget/two_line_text.dart';
|
||||
|
||||
|
||||