mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix: SystemType(#184) & opt.: ios home widget
This commit is contained in:
12
README.md
12
README.md
@@ -47,26 +47,26 @@ If ServerBox app has any bug, please open an [issue](https://github.com/lollipop
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/server.png">
|
<img width="277px" src="imgs/server.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/detail.png">
|
<img width="277px" src="imgs/detail.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/sftp.png">
|
<img width="277px" src="imgs/sftp.png">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/editor.png">
|
<img width="277px" src="imgs/editor.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/ssh.png">
|
<img width="277px" src="imgs/ssh.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/docker.png">
|
<img width="277px" src="imgs/docker.png">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
12
README_zh.md
12
README_zh.md
@@ -47,26 +47,26 @@
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/server.png">
|
<img width="277px" src="imgs/server.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/detail.png">
|
<img width="277px" src="imgs/detail.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/sftp.png">
|
<img width="277px" src="imgs/sftp.png">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/editor.png">
|
<img width="277px" src="imgs/editor.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/ssh.png">
|
<img width="277px" src="imgs/ssh.png">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<img width="200px" src="imgs/docker.png">
|
<img width="277px" src="imgs/docker.png">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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 = 588;
|
CURRENT_PROJECT_VERSION = 589;
|
||||||
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.588;
|
MARKETING_VERSION = 1.0.589;
|
||||||
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;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
let accessoryKey = "accessory_widget_url"
|
||||||
|
|
||||||
extension Date {
|
extension Date {
|
||||||
func toStr() -> String {
|
func toStr() -> String {
|
||||||
let formatter = DateFormatter()
|
let formatter = DateFormatter()
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
import WidgetKit
|
import WidgetKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Intents
|
import Intents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
let demoStatus = Status(name: "Server", cpu: "31.7%", mem: "1.3g / 1.9g", disk: "7.1g / 30.0g", net: "712.3k / 1.2m")
|
let demoStatus = Status(name: "Server", cpu: "31.7%", mem: "1.3g / 1.9g", disk: "7.1g / 30.0g", net: "712.3k / 1.2m")
|
||||||
let domain = "com.lollipopkit.toolbox"
|
let domain = "com.lollipopkit.toolbox"
|
||||||
var url: String?
|
let bgColor = DynamicColor(dark: UIColor.black, light: UIColor.white)
|
||||||
|
|
||||||
struct Provider: IntentTimelineProvider {
|
struct Provider: IntentTimelineProvider {
|
||||||
func placeholder(in context: Context) -> SimpleEntry {
|
func placeholder(in context: Context) -> SimpleEntry {
|
||||||
@@ -24,11 +25,18 @@ struct Provider: IntentTimelineProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
||||||
url = configuration.url
|
var url = configuration.url
|
||||||
|
|
||||||
|
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||||
|
if #available(iOSApplicationExtension 16.0, *) {
|
||||||
|
if family == .accessoryInline || family == .accessoryRectangular {
|
||||||
|
url = UserDefaults.standard.string(forKey: accessoryKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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: 30, to: currentDate)!
|
||||||
StatusLoader.fetch { result in
|
StatusLoader.fetch(url: url) { result in
|
||||||
let entry: SimpleEntry
|
let entry: SimpleEntry
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let status):
|
case .success(let status):
|
||||||
@@ -55,36 +63,61 @@ struct SimpleEntry: TimelineEntry {
|
|||||||
struct StatusWidgetEntryView : View {
|
struct StatusWidgetEntryView : View {
|
||||||
var entry: Provider.Entry
|
var entry: Provider.Entry
|
||||||
|
|
||||||
|
@Environment(\.widgetFamily) var family: WidgetFamily
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch entry.state {
|
switch entry.state {
|
||||||
case .loading:
|
case .loading:
|
||||||
ProgressView().padding()
|
ProgressView().widgetBackground()
|
||||||
case .error(let descriotion):
|
case .error(let descriotion):
|
||||||
Text(descriotion).padding(.all, 13)
|
Text(descriotion).widgetBackground()
|
||||||
case .normal(let data):
|
case .normal(let data):
|
||||||
let sumColor: Color = .primary.opacity(0.7)
|
let sumColor: Color = .primary.opacity(0.7)
|
||||||
VStack(alignment: .leading, spacing: 3.7) {
|
switch family {
|
||||||
Text(data.name).font(.system(.title3, design: .monospaced))
|
case .accessoryRectangular:
|
||||||
Spacer()
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
DetailItem(icon: "cpu", text: data.cpu, color: sumColor)
|
HStack {
|
||||||
DetailItem(icon: "memorychip", text: data.mem, color: sumColor)
|
Text(data.name)
|
||||||
DetailItem(icon: "externaldrive", text: data.disk, color: sumColor)
|
.font(.system(size: 15, weight: .semibold, design: .monospaced))
|
||||||
DetailItem(icon: "network", text: data.net, color: sumColor)
|
Spacer()
|
||||||
Spacer()
|
CirclePercent(percent: data.cpu)
|
||||||
DetailItem(icon: "clock", text: entry.date.toStr(), color: sumColor)
|
.padding(.top, 3)
|
||||||
|
.padding(.trailing, 3)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
|
Spacer()
|
||||||
|
DetailItem(icon: "memorychip", text: data.mem, color: sumColor)
|
||||||
|
DetailItem(icon: "externaldrive", text: data.disk, color: sumColor)
|
||||||
|
DetailItem(icon: "network", text: data.net, color: sumColor)
|
||||||
|
}
|
||||||
|
.widgetBackground()
|
||||||
|
case .accessoryInline:
|
||||||
|
Text("\(data.name) \(data.cpu)").widgetBackground()
|
||||||
|
default:
|
||||||
|
VStack(alignment: .leading, spacing: 3.7) {
|
||||||
|
Text(data.name).font(.system(.title3, design: .monospaced))
|
||||||
|
Spacer()
|
||||||
|
DetailItem(icon: "cpu", text: data.cpu, color: sumColor)
|
||||||
|
DetailItem(icon: "memorychip", text: data.mem, color: sumColor)
|
||||||
|
DetailItem(icon: "externaldrive", text: data.disk, color: sumColor)
|
||||||
|
DetailItem(icon: "network", text: data.net, color: sumColor)
|
||||||
|
Spacer()
|
||||||
|
DetailItem(icon: "clock", text: entry.date.toStr(), color: sumColor)
|
||||||
|
.padding(.bottom, 3)
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||||
|
.autoPadding()
|
||||||
|
.widgetBackground()
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
|
||||||
.autoPadding()
|
|
||||||
.widgetBackground()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension View {
|
extension View {
|
||||||
// Set bg to Color.black in Night, Color.white in Day
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
func widgetBackground() -> some View {
|
func widgetBackground() -> some View {
|
||||||
let backgroundView = Color(UIColor.systemBackground)
|
// Set bg to black in Night, white in Day
|
||||||
|
let backgroundView = Color(bgColor.resolve())
|
||||||
if #available(iOS 17.0, *) {
|
if #available(iOS 17.0, *) {
|
||||||
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground
|
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground
|
||||||
containerBackground(for: .widget) {
|
containerBackground(for: .widget) {
|
||||||
@@ -103,10 +136,6 @@ extension View {
|
|||||||
// iOS 17 will auto add a SafeArea, so when iOS < 17, add .padding(.all, 17)
|
// iOS 17 will auto add a SafeArea, so when iOS < 17, add .padding(.all, 17)
|
||||||
func autoPadding() -> some View {
|
func autoPadding() -> some View {
|
||||||
if #available(iOS 17.0, *) {
|
if #available(iOS 17.0, *) {
|
||||||
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground
|
|
||||||
if (showsWidgetContainerBackground) {
|
|
||||||
return self.padding(.all, 17)
|
|
||||||
}
|
|
||||||
return self
|
return self
|
||||||
} else {
|
} else {
|
||||||
return self.padding(.all, 17)
|
return self.padding(.all, 17)
|
||||||
@@ -123,11 +152,12 @@ struct StatusWidget: Widget {
|
|||||||
}
|
}
|
||||||
.configurationDisplayName("Status")
|
.configurationDisplayName("Status")
|
||||||
.description("Status of your servers.")
|
.description("Status of your servers.")
|
||||||
.supportedFamilies([.systemSmall])
|
|
||||||
if #available(iOS 16.0, *) {
|
if #available(iOSApplicationExtension 16.0, *) {
|
||||||
let _ = cfg.supportedFamilies([.accessoryInline, .accessoryCircular])
|
return cfg.supportedFamilies([.systemSmall, .accessoryRectangular, .accessoryInline])
|
||||||
|
} else {
|
||||||
|
return cfg.supportedFamilies([.systemSmall])
|
||||||
}
|
}
|
||||||
return cfg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +169,7 @@ struct StatusWidget_Previews: PreviewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct StatusLoader {
|
struct StatusLoader {
|
||||||
static func fetch(completion: @escaping (Result<Status, Error>) -> Void) {
|
static func fetch(url: String?, completion: @escaping (Result<Status, Error>) -> Void) {
|
||||||
guard let url = url, url.count >= 12 else {
|
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"])))
|
completion(.failure(NSError(domain: domain, code: 0, userInfo: [NSLocalizedDescriptionKey: "https://github.com/lollipopkit/server_box_monitor/wiki"])))
|
||||||
return
|
return
|
||||||
@@ -148,6 +178,9 @@ struct StatusLoader {
|
|||||||
completion(.failure(NSError(domain: domain, code: 1, userInfo: [NSLocalizedDescriptionKey: "url is invalid"])))
|
completion(.failure(NSError(domain: domain, code: 1, userInfo: [NSLocalizedDescriptionKey: "url is invalid"])))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserDefaults.standard.set(url.absoluteString, forKey: accessoryKey)
|
||||||
|
|
||||||
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
|
||||||
if error != nil {
|
if error != nil {
|
||||||
completion(.failure(error!))
|
completion(.failure(error!))
|
||||||
@@ -173,7 +206,7 @@ struct StatusLoader {
|
|||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
default:
|
default:
|
||||||
let msg = jsonAll["msg"] as? String ?? ""
|
let msg = jsonAll["msg"] as? String ?? "Empty err"
|
||||||
return .failure(NSError(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey: msg]))
|
return .failure(NSError(domain: domain, code: code, userInfo: [NSLocalizedDescriptionKey: msg]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,3 +235,49 @@ struct DetailItem: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DetailItemSmall: View {
|
||||||
|
let icon: String
|
||||||
|
let text: String
|
||||||
|
let color: Color
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(spacing: 6.7) {
|
||||||
|
Image(systemName: icon).resizable().foregroundColor(color).frame(width: 11, height: 11, alignment: .center)
|
||||||
|
Text(text)
|
||||||
|
.font(.system(size: 11, design: .monospaced))
|
||||||
|
.foregroundColor(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空心圆,显示百分比
|
||||||
|
struct CirclePercent: View {
|
||||||
|
// eg: 31.7%
|
||||||
|
let percent: String
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
// 31.7% -> 0.317
|
||||||
|
let percentD = Double(percent.trimmingCharacters(in: .init(charactersIn: "%")))
|
||||||
|
let double = (percentD ?? 0) / 100
|
||||||
|
Circle()
|
||||||
|
.trim(from: 0, to: CGFloat(double))
|
||||||
|
.stroke(Color.primary, lineWidth: 3)
|
||||||
|
.animation(.easeInOut(duration: 0.5))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DynamicColor {
|
||||||
|
let dark: UIColor
|
||||||
|
let light: UIColor
|
||||||
|
|
||||||
|
func resolve() -> UIColor {
|
||||||
|
if #available(iOS 13, *) { // 版本号大于等于13
|
||||||
|
return UIColor { (traitCollection: UITraitCollection) -> UIColor in
|
||||||
|
return traitCollection.userInterfaceStyle == UIUserInterfaceStyle.dark ?
|
||||||
|
self.dark : self.light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self.light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,15 +9,16 @@ enum SystemType {
|
|||||||
|
|
||||||
const SystemType._(this.value);
|
const SystemType._(this.value);
|
||||||
|
|
||||||
static SystemType? parse(String? value) {
|
static SystemType parse(String value) {
|
||||||
if (value == null) return null;
|
switch (value.trim()) {
|
||||||
switch (value) {
|
|
||||||
case linuxSign:
|
case linuxSign:
|
||||||
return SystemType.linux;
|
return SystemType.linux;
|
||||||
case bsdSign:
|
case bsdSign:
|
||||||
return SystemType.bsd;
|
return SystemType.bsd;
|
||||||
|
default:
|
||||||
|
// Fallback to linux
|
||||||
|
return SystemType.linux;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSegmentsLenMatch(int len) => len == segmentsLen;
|
bool isSegmentsLenMatch(int len) => len == segmentsLen;
|
||||||
|
|||||||
@@ -329,10 +329,10 @@ class ServerProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final systemType = SystemType.parse(segments[0]);
|
final systemType = SystemType.parse(segments[0]);
|
||||||
if (systemType == null || !systemType.isSegmentsLenMatch(segments.length)) {
|
if (!systemType.isSegmentsLenMatch(segments.length)) {
|
||||||
_limiter.inc(sid);
|
_limiter.inc(sid);
|
||||||
s.status.failedInfo =
|
s.status.failedInfo =
|
||||||
'Segments not match: expect ${systemType?.segmentsLen}, got ${segments.length}';
|
'Segments not match: expect ${systemType.segmentsLen}, got ${segments.length}';
|
||||||
_setServerState(s, ServerState.failed);
|
_setServerState(s, ServerState.failed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 588;
|
static const int build = 589;
|
||||||
static const String engine = "3.13.6";
|
static const String engine = "3.13.6";
|
||||||
static const String buildAt = "2023-10-13 14:38:17";
|
static const String buildAt = "2023-10-14 12:09:35";
|
||||||
static const int modifications = 5;
|
static const int modifications = 6;
|
||||||
static const int script = 21;
|
static const int script = 21;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user