mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
opt.: ios home widget
This commit is contained in:
@@ -586,7 +586,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -596,7 +596,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -720,7 +720,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -730,7 +730,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -748,7 +748,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -758,7 +758,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -779,7 +779,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -792,7 +792,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||||
@@ -818,7 +818,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -831,7 +831,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -854,7 +854,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -867,7 +867,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -890,7 +890,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -902,7 +902,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||||
@@ -931,7 +931,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -943,7 +943,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||||
PRODUCT_NAME = ServerBox;
|
PRODUCT_NAME = ServerBox;
|
||||||
@@ -969,7 +969,7 @@
|
|||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 596;
|
CURRENT_PROJECT_VERSION = 597;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -981,7 +981,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.596;
|
MARKETING_VERSION = 1.0.597;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
|
||||||
PRODUCT_NAME = ServerBox;
|
PRODUCT_NAME = ServerBox;
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import Flutter
|
|||||||
|
|
||||||
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||||
let methodChannel = FlutterMethodChannel(name: "tech.lolli.toolbox/home_widget", binaryMessenger: controller.binaryMessenger)
|
let methodChannel = FlutterMethodChannel(name: "tech.lolli.toolbox/home_widget", binaryMessenger: controller.binaryMessenger)
|
||||||
methodChannel.setMethodCallHandler({
|
methodChannel.setMethodCallHandler({(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
|
||||||
if call.method == "update" {
|
if call.method == "update" {
|
||||||
if #available(iOS 14.0, *) {
|
if #available(iOS 14.0, *) {
|
||||||
WidgetCenter.shared.reloadTimelines(ofKind: "StatusWidget")
|
WidgetCenter.shared.reloadTimelines(ofKind: "StatusWidget")
|
||||||
@@ -22,4 +21,13 @@ import Flutter
|
|||||||
})
|
})
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||||
|
if url.scheme == "https" || url.scheme == "http" {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
} else {
|
||||||
|
// Pass
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import Foundation
|
|||||||
|
|
||||||
let accessoryKey = "accessory_widget_url"
|
let accessoryKey = "accessory_widget_url"
|
||||||
|
|
||||||
|
let helpUrl = URL(string: "https://github.com/lollipopkit/flutter_server_box/wiki#home-widget--watchos-app")!
|
||||||
|
|
||||||
extension Date {
|
extension Date {
|
||||||
func toStr() -> String {
|
func toStr() -> String {
|
||||||
let formatter = DateFormatter()
|
let formatter = DateFormatter()
|
||||||
@@ -19,9 +21,14 @@ extension Date {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ErrType: Error {
|
||||||
|
case url(String)
|
||||||
|
case http(String)
|
||||||
|
}
|
||||||
|
|
||||||
enum ContentState {
|
enum ContentState {
|
||||||
case loading
|
case loading
|
||||||
case error(String)
|
case error(ErrType)
|
||||||
case normal(Status)
|
case normal(Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,23 +36,58 @@ struct Provider: IntentTimelineProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentDate = Date()
|
let currentDate = Date()
|
||||||
let refreshDate = Calendar.current.date(byAdding: .minute, value: 30, to: currentDate)!
|
let refreshDate = Calendar.current.date(byAdding: .minute, value: 15, to: currentDate)!
|
||||||
StatusLoader.fetch(url: url) { result in
|
fetch(url: url) { result in
|
||||||
let entry: SimpleEntry
|
let entry: SimpleEntry = SimpleEntry(
|
||||||
switch result {
|
|
||||||
case .success(let status):
|
|
||||||
entry = SimpleEntry(
|
|
||||||
date: currentDate,
|
date: currentDate,
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
state: .normal(status)
|
state: result
|
||||||
)
|
)
|
||||||
case .failure(let err):
|
|
||||||
entry = SimpleEntry(date: currentDate, configuration: configuration, state: .error(err.localizedDescription))
|
|
||||||
}
|
|
||||||
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
|
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
|
||||||
completion(timeline)
|
completion(timeline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetch(url: String?, completion: @escaping (ContentState) -> Void) {
|
||||||
|
guard let url = url, url.count >= 12 else {
|
||||||
|
completion(.error(.url("url is nil OR len < 12")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let url = URL(string: url) else {
|
||||||
|
completion(.error(.url("parse url failed")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
completion(.loading)
|
||||||
|
|
||||||
|
UserDefaults.standard.set(url.absoluteString, forKey: accessoryKey)
|
||||||
|
|
||||||
|
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
||||||
|
if error != nil {
|
||||||
|
completion(.error(.http(error?.localizedDescription ?? "unknown http err")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let data = data else {
|
||||||
|
completion(.error(.http("empty http data")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let jsonAll = try! JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
|
||||||
|
let code = jsonAll["code"] as? Int ?? 1
|
||||||
|
if (code != 0) {
|
||||||
|
let msg = jsonAll["msg"] as? String ?? "Empty err"
|
||||||
|
completion(.error(.http(msg)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = jsonAll["data"] as? [String: Any] ?? [:]
|
||||||
|
let name = json["name"] as? String ?? ""
|
||||||
|
let disk = json["disk"] as? String ?? ""
|
||||||
|
let cpu = json["cpu"] as? String ?? ""
|
||||||
|
let mem = json["mem"] as? String ?? ""
|
||||||
|
let net = json["net"] as? String ?? ""
|
||||||
|
completion(.normal(Status(name: name, cpu: cpu, mem: mem, disk: disk, net: net)))
|
||||||
|
}
|
||||||
|
task.resume()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimpleEntry: TimelineEntry {
|
struct SimpleEntry: TimelineEntry {
|
||||||
@@ -70,8 +105,25 @@ struct StatusWidgetEntryView : View {
|
|||||||
switch entry.state {
|
switch entry.state {
|
||||||
case .loading:
|
case .loading:
|
||||||
ProgressView().widgetBackground()
|
ProgressView().widgetBackground()
|
||||||
case .error(let descriotion):
|
case .error(let err):
|
||||||
Text(descriotion).widgetBackground()
|
switch err {
|
||||||
|
case .http(let description):
|
||||||
|
VStack(alignment: .center) {
|
||||||
|
Text(description)
|
||||||
|
if #available(iOS 17.0, *) {
|
||||||
|
Button(intent: RefreshIntent()) {
|
||||||
|
Image(systemName: "arrow.clockwise")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 10, height: 12.7)
|
||||||
|
}
|
||||||
|
tint(.gray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.widgetBackground()
|
||||||
|
case .url(let _):
|
||||||
|
Link("Open wiki ⬅️", destination: helpUrl)
|
||||||
|
.widgetBackground()
|
||||||
|
}
|
||||||
case .normal(let data):
|
case .normal(let data):
|
||||||
let sumColor: Color = .primary.opacity(0.7)
|
let sumColor: Color = .primary.opacity(0.7)
|
||||||
switch family {
|
switch family {
|
||||||
@@ -133,14 +185,8 @@ extension View {
|
|||||||
// Set bg to black in Night, white in Day
|
// Set bg to black in Night, white in Day
|
||||||
let backgroundView = Color(bgColor.resolve())
|
let backgroundView = Color(bgColor.resolve())
|
||||||
if #available(iOS 17.0, *) {
|
if #available(iOS 17.0, *) {
|
||||||
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground
|
|
||||||
containerBackground(for: .widget) {
|
containerBackground(for: .widget) {
|
||||||
// If it's show in StandBy
|
|
||||||
if showsWidgetContainerBackground {
|
|
||||||
backgroundView
|
backgroundView
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
background(backgroundView)
|
background(backgroundView)
|
||||||
@@ -161,20 +207,15 @@ struct StatusWidget: Widget {
|
|||||||
let kind: String = "StatusWidget"
|
let kind: String = "StatusWidget"
|
||||||
|
|
||||||
var body: some WidgetConfiguration {
|
var body: some WidgetConfiguration {
|
||||||
|
let cfg = IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
|
||||||
|
StatusWidgetEntryView(entry: entry)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("Status")
|
||||||
|
.description("Status of your servers.")
|
||||||
if #available(iOSApplicationExtension 16.0, *) {
|
if #available(iOSApplicationExtension 16.0, *) {
|
||||||
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
|
return cfg.supportedFamilies([.systemSmall, .accessoryRectangular, .accessoryInline])
|
||||||
StatusWidgetEntryView(entry: entry)
|
|
||||||
}
|
|
||||||
.configurationDisplayName("Status")
|
|
||||||
.description("Status of your servers.")
|
|
||||||
.supportedFamilies([.systemSmall, .accessoryRectangular, .accessoryInline])
|
|
||||||
} else {
|
} else {
|
||||||
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
|
return cfg.supportedFamilies([.systemSmall])
|
||||||
StatusWidgetEntryView(entry: entry)
|
|
||||||
}
|
|
||||||
.configurationDisplayName("Status")
|
|
||||||
.description("Status of your servers.")
|
|
||||||
.supportedFamilies([.systemSmall])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,59 +227,6 @@ struct StatusWidget_Previews: PreviewProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StatusLoader {
|
|
||||||
static func fetch(url: String?, completion: @escaping (Result<Status, Error>) -> Void) {
|
|
||||||
guard let url = url, url.count >= 12 else {
|
|
||||||
completion(.failure(NSError(domain: domain, code: 0, userInfo: [NSLocalizedDescriptionKey: "https://github.com/lollipopkit/server_box_monitor/wiki"])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let url = URL(string: url) else {
|
|
||||||
completion(.failure(NSError(domain: domain, code: 1, userInfo: [NSLocalizedDescriptionKey: "url is invalid"])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
UserDefaults.standard.set(url.absoluteString, forKey: accessoryKey)
|
|
||||||
|
|
||||||
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
|
||||||
if error != nil {
|
|
||||||
completion(.failure(error!))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let data = data else {
|
|
||||||
completion(.failure(NSError(domain: domain, code: 2, userInfo: [NSLocalizedDescriptionKey: "empty network data."])))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch getStatus(fromData: data) {
|
|
||||||
case .success(let status):
|
|
||||||
completion(.success(status))
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task.resume()
|
|
||||||
}
|
|
||||||
|
|
||||||
static func getStatus(fromData data: Foundation.Data) -> Result<Status, Error> {
|
|
||||||
let jsonAll = try! JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
|
|
||||||
let code = jsonAll["code"] as? Int ?? 1
|
|
||||||
if (code != 0) {
|
|
||||||
switch (code) {
|
|
||||||
default:
|
|
||||||
let msg = jsonAll["msg"] as? String ?? "Empty err"
|
|
||||||
return .failure(NSError(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey: msg]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let json = jsonAll["data"] as? [String: Any] ?? [:]
|
|
||||||
let name = json["name"] as? String ?? ""
|
|
||||||
let disk = json["disk"] as? String ?? ""
|
|
||||||
let cpu = json["cpu"] as? String ?? ""
|
|
||||||
let mem = json["mem"] as? String ?? ""
|
|
||||||
let net = json["net"] as? String ?? ""
|
|
||||||
return .success(Status(name: name, cpu: cpu, mem: mem, disk: disk, net: net))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DetailItem: View {
|
struct DetailItem: View {
|
||||||
let icon: String
|
let icon: String
|
||||||
let text: String
|
let text: String
|
||||||
@@ -291,7 +279,6 @@ struct RefreshIntent: AppIntent {
|
|||||||
static var description = IntentDescription("Refresh status.")
|
static var description = IntentDescription("Refresh status.")
|
||||||
|
|
||||||
func perform() async throws -> some IntentResult {
|
func perform() async throws -> some IntentResult {
|
||||||
|
|
||||||
return .result()
|
return .result()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,13 +41,19 @@ struct PageView: View {
|
|||||||
ProgressView().padding().onAppear {
|
ProgressView().padding().onAppear {
|
||||||
getStatus(url: url!)
|
getStatus(url: url!)
|
||||||
}
|
}
|
||||||
case .error(let string):
|
case .error(let err):
|
||||||
VStack {
|
switch err {
|
||||||
Spacer()
|
case .http(let description):
|
||||||
Image(systemName: "exclamationmark.triangle.fill").foregroundColor(.red)
|
VStack(alignment: .center) {
|
||||||
Spacer()
|
Text(description)
|
||||||
Text(string).padding()
|
Button(action: {
|
||||||
Spacer()
|
state = .loading
|
||||||
|
}){
|
||||||
|
Image(systemName: "arrow.clockwise")
|
||||||
|
}.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
case .emptyUrl, .invalidUrl:
|
||||||
|
Link("View help", destination: helpUrl)
|
||||||
}
|
}
|
||||||
case .normal(let status):
|
case .normal(let status):
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
@@ -73,33 +79,33 @@ struct PageView: View {
|
|||||||
func getStatus(url: String) {
|
func getStatus(url: String) {
|
||||||
state = .loading
|
state = .loading
|
||||||
if url.count < 12 {
|
if url.count < 12 {
|
||||||
state = .error("url is too short")
|
state = .error(.url("url len < 12"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let url = URL(string: url) else {
|
guard let url = URL(string: url) else {
|
||||||
state = .error("url is invalid")
|
state = .error(.url("parse url failed"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
||||||
guard error == nil else {
|
guard error == nil else {
|
||||||
state = .error(error!.localizedDescription)
|
state = .error(.http(error!.localizedDescription))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let data = data else {
|
guard let data = data else {
|
||||||
state = .error("data is nil")
|
state = .error(.http("empty data"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let jsonAll = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
|
guard let jsonAll = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
|
||||||
state = .error("json parse fail")
|
state = .error(.http("json parse fail"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let code = jsonAll["code"] as? Int else {
|
guard let code = jsonAll["code"] as? Int else {
|
||||||
state = .error("code is nil")
|
state = .error(.http("code is nil"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
let msg = jsonAll["msg"] as? String ?? ""
|
let msg = jsonAll["msg"] as? String ?? ""
|
||||||
state = .error(msg)
|
state = .error(.http(msg))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 596;
|
static const int build = 597;
|
||||||
static const String engine = "3.13.7";
|
static const String engine = "3.13.7";
|
||||||
static const String buildAt = "2023-10-14 23:24:14";
|
static const String buildAt = "2023-10-15 13:38:49";
|
||||||
static const int modifications = 1;
|
static const int modifications = 9;
|
||||||
static const int script = 21;
|
static const int script = 21;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user