diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart
index bdc7df95..cac774c7 100644
--- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart
+++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart
@@ -528,6 +528,12 @@ abstract class S {
/// **'Go to'**
String get goto;
+ /// No description provided for @homeWidgetUrlConfig.
+ ///
+ /// In en, this message translates to:
+ /// **'Config home widget url'**
+ String get homeWidgetUrlConfig;
+
/// No description provided for @host.
///
/// In en, this message translates to:
diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart
index f62c4270..2aba3f1c 100644
--- a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart
+++ b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart
@@ -236,6 +236,9 @@ class SDe extends S {
@override
String get goto => 'Pfad öffnen';
+ @override
+ String get homeWidgetUrlConfig => 'Home-Widget-Link konfigurieren';
+
@override
String get host => 'Host';
diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart
index c670b806..b554f58c 100644
--- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart
+++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart
@@ -236,6 +236,9 @@ class SEn extends S {
@override
String get goto => 'Go to';
+ @override
+ String get homeWidgetUrlConfig => 'Config home widget url';
+
@override
String get host => 'Host';
diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart
index d221b572..927588d7 100644
--- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart
+++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart
@@ -236,6 +236,9 @@ class SZh extends S {
@override
String get goto => '前往';
+ @override
+ String get homeWidgetUrlConfig => '桌面部件链接配置';
+
@override
String get host => '主机';
@@ -885,6 +888,9 @@ class SZhTw extends SZh {
@override
String get goto => '前往';
+ @override
+ String get homeWidgetUrlConfig => '桌面部件鏈接配置';
+
@override
String get host => '主機';
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7b1ca95c..6a2f204b 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -36,5 +36,25 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
new file mode 100644
index 00000000..64c4e2a8
--- /dev/null
+++ b/android/app/src/main/kotlin/tech/lolli/toolbox/widget/HomeWidget.kt
@@ -0,0 +1,76 @@
+package tech.lolli.toolbox.widget
+
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetProvider
+import android.content.Context
+import android.content.Intent
+import android.view.View
+import android.widget.RemoteViews
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import org.json.JSONObject
+import tech.lolli.toolbox.R
+import java.net.URL
+
+class HomeWidget : AppWidgetProvider() {
+ override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
+ for (appWidgetId in appWidgetIds) {
+ updateAppWidget(context, appWidgetManager, appWidgetId)
+ }
+ }
+
+ @OptIn(DelicateCoroutinesApi::class)
+ private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
+ val views = RemoteViews(context.packageName, R.layout.home_widget)
+ val sp = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
+ var url = sp.getString("$appWidgetId", null)
+ val gUrl = sp.getString("*", null)
+ if (url.isNullOrEmpty()) {
+ url = gUrl
+ }
+
+ if (url.isNullOrEmpty()) {
+ views.setViewVisibility(R.id.widget_cpu_label, View.INVISIBLE)
+ views.setViewVisibility(R.id.widget_mem_label, View.INVISIBLE)
+ views.setViewVisibility(R.id.widget_disk_label, View.INVISIBLE)
+ views.setViewVisibility(R.id.widget_net_label, View.INVISIBLE)
+ views.setTextViewText(R.id.widget_name, "ID: $appWidgetId")
+ appWidgetManager.updateAppWidget(appWidgetId, views)
+ return
+ }
+
+ GlobalScope.launch(Dispatchers.IO) {
+ val jsonStr = URL(url).readText()
+ val jsonObject = JSONObject(jsonStr)
+ val data = jsonObject.getJSONObject("data")
+ val server = data.getString("name")
+ val cpu = data.getString("cpu")
+ val mem = data.getString("mem")
+ val disk = data.getString("disk")
+ val net = data.getString("net")
+
+ GlobalScope.launch(Dispatchers.Main) {
+ // mem or disk is empty -> get status failed
+ // (cpu | net) isEmpty -> data is not ready
+ if (mem.isEmpty() || disk.isEmpty()) {
+ return@launch
+ }
+ views.setTextViewText(R.id.widget_name, server)
+
+ views.setTextViewText(R.id.widget_cpu, cpu)
+ views.setTextViewText(R.id.widget_mem, mem)
+ views.setTextViewText(R.id.widget_disk, disk)
+ views.setTextViewText(R.id.widget_net, net)
+
+ // eg: 17:17
+ val timeStr = android.text.format.DateFormat.format("HH:mm", java.util.Date()).toString()
+ views.setTextViewText(R.id.widget_time, timeStr)
+
+ appWidgetManager.updateAppWidget(appWidgetId, views)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/memory_24.xml b/android/app/src/main/res/drawable/memory_24.xml
new file mode 100644
index 00000000..782f0334
--- /dev/null
+++ b/android/app/src/main/res/drawable/memory_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/net_24.xml b/android/app/src/main/res/drawable/net_24.xml
new file mode 100644
index 00000000..b42514db
--- /dev/null
+++ b/android/app/src/main/res/drawable/net_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/settings_24.xml b/android/app/src/main/res/drawable/settings_24.xml
new file mode 100644
index 00000000..bc9438a9
--- /dev/null
+++ b/android/app/src/main/res/drawable/settings_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/speed_24.xml b/android/app/src/main/res/drawable/speed_24.xml
new file mode 100644
index 00000000..56ecc4d7
--- /dev/null
+++ b/android/app/src/main/res/drawable/speed_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/storage_24.xml b/android/app/src/main/res/drawable/storage_24.xml
new file mode 100644
index 00000000..2ae99d06
--- /dev/null
+++ b/android/app/src/main/res/drawable/storage_24.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/widget_background.xml b/android/app/src/main/res/drawable/widget_background.xml
new file mode 100644
index 00000000..a8a58821
--- /dev/null
+++ b/android/app/src/main/res/drawable/widget_background.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/home_widget.xml b/android/app/src/main/res/layout/home_widget.xml
new file mode 100644
index 00000000..df71bc78
--- /dev/null
+++ b/android/app/src/main/res/layout/home_widget.xml
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml
new file mode 100644
index 00000000..252bf018
--- /dev/null
+++ b/android/app/src/main/res/values-night/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #000000
+ #FFFFFF
+ #BBBBBB
+
\ No newline at end of file
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..e3ae284f
--- /dev/null
+++ b/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+
+
+ #EEEEEE
+ #FFFFFF
+ #000000
+ #333333
+
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/home_widget.xml b/android/app/src/main/res/xml/home_widget.xml
new file mode 100644
index 00000000..b26ca598
--- /dev/null
+++ b/android/app/src/main/res/xml/home_widget.xml
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 77f5737a..5091e2dc 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -17,7 +17,6 @@
E33A3E392A626DCD009744AB /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E33A3E382A626DCD009744AB /* SwiftUI.framework */; };
E33A3E3C2A626DCE009744AB /* StatusWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A3E3B2A626DCE009744AB /* StatusWidgetBundle.swift */; };
E33A3E402A626DCE009744AB /* StatusWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = E33A3E3F2A626DCE009744AB /* StatusWidget.swift */; };
- E33A3E432A626DD0009744AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E33A3E422A626DD0009744AB /* Assets.xcassets */; };
E33A3E452A626DD0009744AB /* StatusWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = E33A3E412A626DCE009744AB /* StatusWidget.intentdefinition */; };
E33A3E462A626DD0009744AB /* StatusWidget.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = E33A3E412A626DCE009744AB /* StatusWidget.intentdefinition */; };
E33A3E492A626DD0009744AB /* StatusWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E33A3E352A626DCD009744AB /* StatusWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -81,7 +80,6 @@
E33A3E3B2A626DCE009744AB /* StatusWidgetBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusWidgetBundle.swift; sourceTree = ""; };
E33A3E3F2A626DCE009744AB /* StatusWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusWidget.swift; sourceTree = ""; };
E33A3E412A626DCE009744AB /* StatusWidget.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = StatusWidget.intentdefinition; sourceTree = ""; };
- E33A3E422A626DD0009744AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
E33A3E442A626DD0009744AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
E398BF6A29BDB34500FE4FD5 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
E3DB67EC2A31FE200027B8CB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
@@ -182,7 +180,6 @@
E33A3E3B2A626DCE009744AB /* StatusWidgetBundle.swift */,
E33A3E3F2A626DCE009744AB /* StatusWidget.swift */,
E33A3E412A626DCE009744AB /* StatusWidget.intentdefinition */,
- E33A3E422A626DD0009744AB /* Assets.xcassets */,
E33A3E442A626DD0009744AB /* Info.plist */,
);
path = StatusWidget;
@@ -286,7 +283,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- E33A3E432A626DD0009744AB /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -474,7 +470,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -482,7 +478,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -606,7 +602,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -614,7 +610,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -632,7 +628,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -640,7 +636,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -661,7 +657,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -674,7 +670,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 1.0;
+ MARKETING_VERSION = 1.0.377;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -700,7 +696,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -713,7 +709,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 1.0;
+ MARKETING_VERSION = 1.0.377;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -736,7 +732,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
+ CURRENT_PROJECT_VERSION = 377;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -749,7 +745,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = 1.0;
+ MARKETING_VERSION = 1.0.377;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/ios/StatusWidget/StatusWidget.intentdefinition b/ios/StatusWidget/StatusWidget.intentdefinition
index addc6097..a1f860e8 100644
--- a/ios/StatusWidget/StatusWidget.intentdefinition
+++ b/ios/StatusWidget/StatusWidget.intentdefinition
@@ -47,7 +47,7 @@
INIntentParameterMetadataCapitalization
Characters
INIntentParameterMetadataDefaultValue
- https://push.lolli.tech
+ https://
INIntentParameterMetadataDefaultValueID
wwvqC2
INIntentParameterMetadataDisableAutocorrect
diff --git a/ios/StatusWidget/StatusWidget.swift b/ios/StatusWidget/StatusWidget.swift
index a14ab6ca..309c5317 100644
--- a/ios/StatusWidget/StatusWidget.swift
+++ b/ios/StatusWidget/StatusWidget.swift
@@ -70,7 +70,7 @@ struct StatusWidgetEntryView : View {
case .loading:
ProgressView().padding()
case .error(let descriotion):
- Text(descriotion)
+ Text(descriotion).padding(.all, 13)
case .normal:
VStack(alignment: .leading, spacing: 5.7) {
Text(entry.data.name).font(.system(.title3))
@@ -108,8 +108,8 @@ struct StatusWidget_Previews: PreviewProvider {
struct StatusLoader {
static func fetch(completion: @escaping (Result) -> Void) {
- if url == nil || url == "" {
- completion(.failure(NSError(domain: domain, code: 1, userInfo: [NSLocalizedDescriptionKey: "Please longpress it to config first."])))
+ if let url = url, url.count < 12 {
+ completion(.failure(NSError(domain: domain, code: 1, userInfo: [NSLocalizedDescriptionKey: "https://github.com/lollipopkit/server_box_monitor/wiki"])))
return
}
let URL = URL(string: url!)!
@@ -134,7 +134,6 @@ struct StatusLoader {
}
static func getStatus(fromData data: Foundation.Data) -> Result {
-
let jsonAll = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let code = jsonAll["code"] as! Int
if (code != 0) {
@@ -194,7 +193,6 @@ struct DetailItem: View {
func date2String(_ date:Date, dateFormat:String = "yyyy-MM-dd HH:mm:ss") -> String {
let formatter = DateFormatter()
- formatter.locale = Locale.init(identifier: "zh_CN")
formatter.dateFormat = dateFormat
let date = formatter.string(from: date)
return date
diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart
index 57702af3..374139b5 100644
--- a/lib/data/res/build_data.dart
+++ b/lib/data/res/build_data.dart
@@ -2,8 +2,8 @@
class BuildData {
static const String name = "ServerBox";
- static const int build = 376;
- static const String engine = "3.10.5";
- static const String buildAt = "2023-07-08 15:09:08.542818";
- static const int modifications = 2;
+ static const int build = 377;
+ static const String engine = "3.10.6";
+ static const String buildAt = "2023-07-16 23:02:53.506145";
+ static const int modifications = 3;
}
diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb
index 3a97bdf9..262dd163 100644
--- a/lib/l10n/app_de.arb
+++ b/lib/l10n/app_de.arb
@@ -72,6 +72,7 @@
"getPushTokenFailed": "Push-Token kann nicht abgerufen werden",
"gettingToken": "Getting token...",
"goto": "Pfad öffnen",
+ "homeWidgetUrlConfig": "Home-Widget-Link konfigurieren",
"host": "Host",
"httpFailedWithCode": "Anfrage fehlgeschlagen, Statuscode: {code}",
"image": "Image",
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 291d0bbd..2afc3d38 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -72,6 +72,7 @@
"getPushTokenFailed": "Can't fetch push token",
"gettingToken": "Getting token...",
"goto": "Go to",
+ "homeWidgetUrlConfig": "Config home widget url",
"host": "Host",
"httpFailedWithCode": "request failed, status code: {code}",
"image": "Image",
diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb
index a153b1a0..f88704f0 100644
--- a/lib/l10n/app_zh.arb
+++ b/lib/l10n/app_zh.arb
@@ -72,6 +72,7 @@
"getPushTokenFailed": "未能获取到推送token",
"gettingToken": "正在获取Token...",
"goto": "前往",
+ "homeWidgetUrlConfig": "桌面部件链接配置",
"host": "主机",
"httpFailedWithCode": "请求失败, 状态码: {code}",
"image": "镜像",
diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb
index eac1c0c6..57228939 100644
--- a/lib/l10n/app_zh_tw.arb
+++ b/lib/l10n/app_zh_tw.arb
@@ -72,6 +72,7 @@
"getPushTokenFailed": "未能獲取到推送token",
"gettingToken": "正在獲取Token...",
"goto": "前往",
+ "homeWidgetUrlConfig": "桌面部件鏈接配置",
"host": "主機",
"httpFailedWithCode": "請求失敗, 狀態碼: {code}",
"image": "鏡像",
diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart
index fa760546..e4edff05 100644
--- a/lib/view/page/setting.dart
+++ b/lib/view/page/setting.dart
@@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_highlight/theme_map.dart';
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
import 'package:provider/provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
import 'package:toolbox/core/extension/locale.dart';
import 'package:toolbox/core/extension/navigator.dart';
import 'package:toolbox/core/route.dart';
@@ -51,6 +52,7 @@ class _SettingPageState extends State {
late final ServerProvider _serverProvider;
late MediaQueryData _media;
late S _s;
+ late SharedPreferences _sp;
final _selectedColorValue = ValueNotifier(0);
final _launchPageIdx = ValueNotifier(0);
@@ -89,6 +91,8 @@ class _SettingPageState extends State {
_editorDarkTheme.value = _setting.editorDarkTheme.fetch()!;
_keyboardType.value = _setting.keyboardType.fetch()!;
_rotateQuarter.value = _setting.fullScreenRotateQuarter.fetch()!;
+ SharedPreferences.setPrefix('');
+ SharedPreferences.getInstance().then((value) => _sp = value);
}
@override
@@ -141,6 +145,7 @@ class _SettingPageState extends State {
}
if (isAndroid) {
children.add(_buildBgRun());
+ children.add(_buildAndroidWidgetSharedPreference());
}
return Column(
children: children.map((e) => RoundRectCard(e)).toList(),
@@ -836,4 +841,56 @@ class _SettingPageState extends State {
).go(context),
);
}
+
+ void _saveWidgetSP(String data, Map old) {
+ context.pop();
+ try {
+ final map = Map.from(json.decode(data));
+ final keysDel = old.keys.toSet().difference(map.keys.toSet());
+ for (final key in keysDel) {
+ _sp.remove(key);
+ }
+ map.forEach((key, value) {
+ _sp.setString(key, value);
+ });
+ showSnackBar(context, Text(_s.success));
+ } catch (e) {
+ showSnackBar(context, Text(e.toString()));
+ }
+ }
+
+ Widget _buildAndroidWidgetSharedPreference() {
+ return ListTile(
+ title: Text(_s.homeWidgetUrlConfig),
+ trailing: const Icon(Icons.arrow_forward_ios, size: 13),
+ onTap: () {
+ final data = {};
+ _sp.getKeys().forEach((key) {
+ final val = _sp.getString(key);
+ if (val != null) {
+ data[key] = val;
+ }
+ });
+ final ctrl = TextEditingController(text: json.encode(data));
+ showRoundDialog(
+ context: context,
+ title: Text(_s.homeWidgetUrlConfig),
+ child: Input(
+ controller: ctrl,
+ label: 'JSON',
+ type: TextInputType.visiblePassword,
+ maxLines: 7,
+ onSubmitted: (p0) => _saveWidgetSP(p0, data),
+ ),
+ actions: [
+ TextButton(
+ onPressed: () {
+ _saveWidgetSP(ctrl.text, data);
+ },
+ child: Text(_s.ok),
+ ),
+ ]);
+ },
+ );
+ }
}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index bd594ba3..04309f6e 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -8,11 +8,13 @@ import Foundation
import flutter_volume_controller
import path_provider_foundation
import share_plus
+import shared_preferences_foundation
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+ SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj
index b457ebf6..8763239f 100644
--- a/macos/Runner.xcodeproj/project.pbxproj
+++ b/macos/Runner.xcodeproj/project.pbxproj
@@ -475,9 +475,9 @@
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
GENERATE_INFOPLIST_FILE = YES;
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
@@ -490,9 +490,9 @@
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
GENERATE_INFOPLIST_FILE = YES;
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
@@ -505,9 +505,9 @@
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
- CURRENT_PROJECT_VERSION = 376;
+ CURRENT_PROJECT_VERSION = 377;
GENERATE_INFOPLIST_FILE = YES;
- MARKETING_VERSION = 1.0.376;
+ MARKETING_VERSION = 1.0.377;
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
diff --git a/pubspec.lock b/pubspec.lock
index a38bf6b6..cde191c5 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -774,6 +774,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.1"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.2"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
shelf:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 08573d85..eaae2714 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -66,6 +66,7 @@ dependencies:
code_text_field: ^1.1.0
flutter_volume_controller: ^1.2.6
nil: ^1.1.1
+ shared_preferences: ^2.1.1
dev_dependencies:
flutter_native_splash: ^2.1.6