2024-12-14 10:18:13 +00:00
|
|
|
//
|
|
|
|
// SolarWidget.swift
|
|
|
|
// SolarWidget
|
|
|
|
//
|
|
|
|
// Created by LittleSheep on 2024/12/14.
|
|
|
|
//
|
|
|
|
|
|
|
|
import WidgetKit
|
|
|
|
import SwiftUI
|
|
|
|
|
2024-12-14 16:52:42 +00:00
|
|
|
struct CheckInProvider: TimelineProvider {
|
|
|
|
func placeholder(in context: Context) -> CheckInEntry {
|
|
|
|
CheckInEntry(date: Date(), user: nil, checkIn: nil)
|
2024-12-14 10:18:13 +00:00
|
|
|
}
|
|
|
|
|
2024-12-14 16:52:42 +00:00
|
|
|
func getSnapshot(in context: Context, completion: @escaping (CheckInEntry) -> ()) {
|
2024-12-14 10:18:13 +00:00
|
|
|
let prefs = UserDefaults(suiteName: "group.solsynth.solian")
|
|
|
|
|
2024-12-14 11:23:42 +00:00
|
|
|
let dateFormatter = DateFormatter()
|
|
|
|
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"
|
|
|
|
|
2024-12-14 10:18:13 +00:00
|
|
|
let jsonDecoder = JSONDecoder()
|
2024-12-14 11:23:42 +00:00
|
|
|
jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter)
|
2024-12-14 10:18:13 +00:00
|
|
|
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
|
|
|
|
|
|
|
|
let userRaw = prefs?.string(forKey: "user")
|
|
|
|
var user: SolarUser?
|
|
|
|
if let userRaw = userRaw {
|
|
|
|
user = try! jsonDecoder.decode(SolarUser.self, from: userRaw.data(using: .utf8)!)
|
|
|
|
}
|
|
|
|
|
|
|
|
let checkInRaw = prefs?.string(forKey: "today_check_in")
|
|
|
|
var checkIn: SolarCheckInRecord?
|
|
|
|
if let checkInRaw = checkInRaw {
|
|
|
|
checkIn = try! jsonDecoder.decode(SolarCheckInRecord.self, from: checkInRaw.data(using: .utf8)!)
|
|
|
|
}
|
|
|
|
|
2024-12-14 16:52:42 +00:00
|
|
|
let entry = CheckInEntry(
|
2024-12-14 10:18:13 +00:00
|
|
|
date: Date(),
|
|
|
|
user: user,
|
|
|
|
checkIn: checkIn
|
|
|
|
)
|
|
|
|
completion(entry)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
|
|
|
getSnapshot(in: context) { (entry) in
|
|
|
|
let timeline = Timeline(entries: [entry], policy: .atEnd)
|
|
|
|
completion(timeline)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-14 16:52:42 +00:00
|
|
|
struct CheckInEntry: TimelineEntry {
|
2024-12-14 10:18:13 +00:00
|
|
|
let date: Date
|
|
|
|
let user: SolarUser?
|
|
|
|
let checkIn: SolarCheckInRecord?
|
|
|
|
}
|
|
|
|
|
2024-12-14 16:52:42 +00:00
|
|
|
struct CheckInWidgetEntryView : View {
|
|
|
|
var entry: CheckInProvider.Entry
|
2024-12-14 11:23:42 +00:00
|
|
|
|
2024-12-15 10:57:54 +00:00
|
|
|
private let resultTierSymbols: [String] = ["大凶", "凶", "中平", "吉", "大吉"]
|
2024-12-14 11:23:42 +00:00
|
|
|
|
|
|
|
func checkIn() -> Void {}
|
|
|
|
|
|
|
|
func seeDetail() -> Void {}
|
2024-12-14 10:18:13 +00:00
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
VStack(alignment: .leading) {
|
2024-12-14 11:23:42 +00:00
|
|
|
if let checkIn = entry.checkIn {
|
|
|
|
VStack(alignment: .leading) {
|
|
|
|
Text(resultTierSymbols[checkIn.resultTier]).font(.system(size: 27, weight: .bold))
|
|
|
|
Text("+\(checkIn.resultExperience) EXP").font(.system(size: 15, design: .monospaced))
|
|
|
|
}.padding(.horizontal, 4)
|
|
|
|
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
HStack {
|
|
|
|
VStack(alignment: .leading) {
|
|
|
|
Text(
|
|
|
|
checkIn.createdAt,
|
|
|
|
format: .dateTime.weekday()
|
|
|
|
).font(.system(size: 13))
|
|
|
|
Text(
|
|
|
|
checkIn.createdAt,
|
|
|
|
format: .dateTime.day().month()
|
|
|
|
).font(.system(size: 13))
|
|
|
|
}.padding(.leading, 4)
|
|
|
|
|
|
|
|
Button("See Detail", systemImage: "arrow.right", action: seeDetail)
|
|
|
|
.labelStyle(.iconOnly)
|
|
|
|
.buttonBorderShape(.circle)
|
|
|
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
|
|
}.frame(alignment: .bottom)
|
|
|
|
} else {
|
|
|
|
VStack(alignment: .leading) {
|
|
|
|
Text("Check In").font(.system(size: 19, weight: .bold))
|
|
|
|
Text("You haven't check in today").font(.system(size: 15))
|
|
|
|
}.padding(.horizontal, 4)
|
|
|
|
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
HStack(alignment: .bottom) {
|
|
|
|
Button("Check In", systemImage: "checkmark", action: checkIn).labelStyle(.iconOnly).buttonBorderShape(.circle).frame(maxWidth: .infinity, alignment: .trailing)
|
|
|
|
}
|
2024-12-14 10:18:13 +00:00
|
|
|
}
|
2024-12-14 11:23:42 +00:00
|
|
|
}.padding(8)
|
2024-12-14 10:18:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CheckInWidget: Widget {
|
2024-12-14 16:52:42 +00:00
|
|
|
let kind: String = "SolarCheckInWidget"
|
2024-12-14 10:18:13 +00:00
|
|
|
|
|
|
|
var body: some WidgetConfiguration {
|
2024-12-14 16:52:42 +00:00
|
|
|
StaticConfiguration(kind: kind, provider: CheckInProvider()) { entry in
|
2024-12-14 10:18:13 +00:00
|
|
|
if #available(iOS 17.0, *) {
|
2024-12-14 16:52:42 +00:00
|
|
|
CheckInWidgetEntryView(entry: entry)
|
2024-12-14 10:18:13 +00:00
|
|
|
.containerBackground(.fill.tertiary, for: .widget)
|
|
|
|
} else {
|
2024-12-14 16:52:42 +00:00
|
|
|
CheckInWidgetEntryView(entry: entry)
|
2024-12-14 10:18:13 +00:00
|
|
|
.padding()
|
|
|
|
.background()
|
|
|
|
}
|
|
|
|
}
|
2024-12-14 11:23:42 +00:00
|
|
|
.configurationDisplayName("Check In")
|
|
|
|
.description("View your today's fortune on your home screen")
|
2024-12-14 11:25:04 +00:00
|
|
|
.supportedFamilies([.systemSmall, .systemMedium])
|
2024-12-14 10:18:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#Preview(as: .systemSmall) {
|
|
|
|
CheckInWidget()
|
|
|
|
} timeline: {
|
2024-12-14 16:52:42 +00:00
|
|
|
CheckInEntry(date: .now, user: nil, checkIn: nil)
|
|
|
|
CheckInEntry(
|
2024-12-14 10:18:13 +00:00
|
|
|
date: .now,
|
|
|
|
user: SolarUser(id: 1, name: "demo", nick: "Deemo"),
|
2024-12-14 11:23:42 +00:00
|
|
|
checkIn: SolarCheckInRecord(id: 1, resultTier: 1, resultExperience: 100, createdAt: Date.now)
|
2024-12-14 10:18:13 +00:00
|
|
|
)
|
|
|
|
}
|