From e0fab6206a327dfd5548435730e3f70ae6d3fff1 Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Sat, 21 Oct 2023 17:11:14 +0800 Subject: [PATCH] try fix: ios home widget --- ios/StatusWidget/StatusWidget.swift | 150 +++++++++++++++------------- ios/WatchApp/ContentView.swift | 2 +- 2 files changed, 82 insertions(+), 70 deletions(-) diff --git a/ios/StatusWidget/StatusWidget.swift b/ios/StatusWidget/StatusWidget.swift index b2dcc48f77..7f173d7333 100644 --- a/ios/StatusWidget/StatusWidget.swift +++ b/ios/StatusWidget/StatusWidget.swift @@ -17,94 +17,50 @@ let bgColor = DynamicColor(dark: UIColor.black, light: UIColor.white) struct Provider: IntentTimelineProvider { func placeholder(in context: Context) -> SimpleEntry { - SimpleEntry(date: Date(), configuration: ConfigurationIntent(), state: .normal(demoStatus)) + SimpleEntry(date: Date(), configuration: ConfigurationIntent(), isDemo: true) } func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) { - let entry = SimpleEntry(date: Date(), configuration: configuration, state: .normal(demoStatus)) + let entry = SimpleEntry(date: Date(), configuration: configuration, isDemo: true) completion(entry) } func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline) -> ()) { - 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 refreshDate = Calendar.current.date(byAdding: .minute, value: 15, to: currentDate)! - fetch(url: url) { result in - let entry: SimpleEntry = SimpleEntry( - date: currentDate, - configuration: configuration, - state: result - ) - let timeline = Timeline(entries: [entry], policy: .after(refreshDate)) - 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() + let entry: SimpleEntry = SimpleEntry( + date: currentDate, + configuration: configuration, + isDemo: false + ) + let timeline = Timeline(entries: [entry], policy: .after(refreshDate)) + completion(timeline) } } struct SimpleEntry: TimelineEntry { let date: Date let configuration: ConfigurationIntent - let state: ContentState + let isDemo: Bool } struct StatusWidgetEntryView : View { var entry: Provider.Entry @Environment(\.widgetFamily) var family: WidgetFamily + + @State var state: ContentState = .loading var body: some View { - switch entry.state { + switch state { case .loading: - ProgressView().widgetBackground() + ProgressView().widgetBackground().onAppear() { + if entry.isDemo { + state = .normal(demoStatus) + } else { + fetch() + } + } case .error(let err): switch err { case .http(let description): @@ -116,11 +72,11 @@ struct StatusWidgetEntryView : View { .resizable() .frame(width: 10, height: 12.7) } - tint(.gray) + .tint(.gray) } } .widgetBackground() - case .url(let _): + case .url(_): Link("Open wiki ⬅️", destination: helpUrl) .widgetBackground() } @@ -157,7 +113,7 @@ struct StatusWidgetEntryView : View { .resizable() .frame(width: 10, height: 12.7) } - tint(.gray) + .tint(.gray) } } else { Text(data.name).font(.system(.title3, design: .monospaced)) @@ -177,6 +133,56 @@ struct StatusWidgetEntryView : View { } } } + + func fetch() { + var url: String? = entry.configuration.url + if #available(iOS 16.0, *) { + if family == .accessoryInline || family == .accessoryCircular || family == .accessoryRectangular { + url = UserDefaults.standard.string(forKey: accessoryKey) + } + } + + guard let url = url, url.count >= 12 else { + state = .error(.url("url is nil OR len < 12")) + return + } + + guard let url = URL(string: url) else { + state = .error(.url("parse url failed")) + return + } + + let task = URLSession.shared.dataTask(with: url) { (data, response, error) in + DispatchQueue.main.async { + if error != nil { + state = .error(.http(error?.localizedDescription ?? "unknown http err")) + return + } + + guard let data = data else { + state = .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" + state = .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 ?? "" + state = .normal(Status(name: name, cpu: cpu, mem: mem, disk: disk, net: net)) + } + } + task.resume() + } } extension View { @@ -222,8 +228,14 @@ struct StatusWidget: Widget { struct StatusWidget_Previews: PreviewProvider { static var previews: some View { - StatusWidgetEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent(), state: .normal(demoStatus))) - .previewContext(WidgetPreviewContext(family: .systemSmall)) + StatusWidgetEntryView( + entry: SimpleEntry( + date: Date(), + configuration: ConfigurationIntent(), + isDemo: true + ) + ) + .previewContext(WidgetPreviewContext(family: .systemSmall)) } } diff --git a/ios/WatchApp/ContentView.swift b/ios/WatchApp/ContentView.swift index d6cd94f48a..c6b3b66fc3 100644 --- a/ios/WatchApp/ContentView.swift +++ b/ios/WatchApp/ContentView.swift @@ -52,7 +52,7 @@ struct PageView: View { Image(systemName: "arrow.clockwise") }.buttonStyle(.plain) } - case .emptyUrl, .invalidUrl: + case .url(_): Link("View help", destination: helpUrl) } case .normal(let status):