summaryrefslogtreecommitdiffstats
path: root/Solsnu.Widget
diff options
context:
space:
mode:
authorivar <i@oiee.no>2025-12-17 00:16:58 +0100
committerivar <i@oiee.no>2025-12-17 00:16:58 +0100
commitbfd75822b3e9882ff4e85d13a0e3658b60e6329d (patch)
tree223462af215c5ee7eef9e6bcbb48dfbe1b97d1e3 /Solsnu.Widget
parent0e1635b057903434c0f193ad9ead7035150b0773 (diff)
downloadsolverv-master.tar.xz
solverv-master.zip
Initial commitHEADmaster
Diffstat (limited to 'Solsnu.Widget')
-rw-r--r--Solsnu.Widget/Assets.xcassets/AccentColor.colorset/Contents.json11
-rw-r--r--Solsnu.Widget/Assets.xcassets/AppIcon.appiconset/Contents.json35
-rw-r--r--Solsnu.Widget/Assets.xcassets/Contents.json6
-rw-r--r--Solsnu.Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json11
-rw-r--r--Solsnu.Widget/Info.plist11
-rw-r--r--Solsnu.Widget/Solsnu_Widget.swift133
-rw-r--r--Solsnu.Widget/Solsnu_WidgetBundle.swift17
-rw-r--r--Solsnu.Widget/Solsnu_WidgetControl.swift54
8 files changed, 278 insertions, 0 deletions
diff --git a/Solsnu.Widget/Assets.xcassets/AccentColor.colorset/Contents.json b/Solsnu.Widget/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 0000000..eb87897
--- /dev/null
+++ b/Solsnu.Widget/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Solsnu.Widget/Assets.xcassets/AppIcon.appiconset/Contents.json b/Solsnu.Widget/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2305880
--- /dev/null
+++ b/Solsnu.Widget/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,35 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "tinted"
+ }
+ ],
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Solsnu.Widget/Assets.xcassets/Contents.json b/Solsnu.Widget/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/Solsnu.Widget/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Solsnu.Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json b/Solsnu.Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json
new file mode 100644
index 0000000..eb87897
--- /dev/null
+++ b/Solsnu.Widget/Assets.xcassets/WidgetBackground.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Solsnu.Widget/Info.plist b/Solsnu.Widget/Info.plist
new file mode 100644
index 0000000..0f118fb
--- /dev/null
+++ b/Solsnu.Widget/Info.plist
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSExtension</key>
+ <dict>
+ <key>NSExtensionPointIdentifier</key>
+ <string>com.apple.widgetkit-extension</string>
+ </dict>
+</dict>
+</plist>
diff --git a/Solsnu.Widget/Solsnu_Widget.swift b/Solsnu.Widget/Solsnu_Widget.swift
new file mode 100644
index 0000000..bd71672
--- /dev/null
+++ b/Solsnu.Widget/Solsnu_Widget.swift
@@ -0,0 +1,133 @@
+//
+// Solsnu_Widget.swift
+// Solsnu.Widget
+//
+// Created by Ivar Løvlie on 15/12/2025.
+//
+
+import WidgetKit
+import SwiftUI
+
+struct Provider: TimelineProvider {
+ func placeholder(in context: Context) -> SolvervEntry {
+ SolvervEntry(def: SolvervDef(date: Date()))
+ }
+
+ func getSnapshot(in context: Context, completion: @escaping (SolvervEntry) -> ()) {
+ let entry = SolvervEntry(def: SolvervDef(date: Date()))
+ completion(entry)
+ }
+
+ func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
+ var entries: [SolvervEntry] = []
+ let currentDate = Date()
+ for hourOffset in 0 ..< 5 {
+ let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
+ let entry = SolvervEntry(def: SolvervDef(date: currentDate))
+ entries.append(entry)
+ }
+
+ let timeline = Timeline(entries: entries, policy: .atEnd)
+ completion(timeline)
+ }
+}
+
+struct SolvervEntry: TimelineEntry {
+ let date: Date
+ let emoji: String
+ let def: SolvervDef
+
+ init(def: SolvervDef, date: Date? = nil) {
+ self.date = date ?? def.date
+ self.emoji = def.emoji()
+ self.def = def;
+ }
+}
+
+struct Solsnu_WidgetEntryView : View {
+ var entry: Provider.Entry
+
+ var body: some View {
+ VStack {
+ Text("Time:")
+ Text(entry.date, style: .time)
+
+ Text("Emoji:")
+ Text(entry.emoji)
+ }
+ }
+}
+
+struct Solsnu_Widget: Widget {
+ let kind: String = "Solsnu_Widget"
+
+ var body: some WidgetConfiguration {
+ StaticConfiguration(kind: kind, provider: Provider()) { entry in
+ if #available(iOS 17.0, *) {
+ Solsnu_WidgetEntryView(entry: entry)
+ .containerBackground(.fill.tertiary, for: .widget)
+ } else {
+ Solsnu_WidgetEntryView(entry: entry)
+ .padding()
+ .background()
+ }
+ }
+ .configurationDisplayName("My Widget")
+ .description("This is an example widget.")
+ }
+}
+
+#Preview(as: .systemSmall) {
+ Solsnu_Widget()
+} timeline: {
+ SolvervEntry(def: SolvervDef(utcString: "2025-09-22 18:20:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2025-12-21 15:03:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2026-03-20 14:46:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2026-06-21 08:25:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2026-09-23 00:06:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2026-12-21 20:50:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2027-03-20 20:25:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2027-06-21 14:11:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2027-09-23 06:02:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2027-12-22 02:43:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2028-03-20 02:17:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2028-06-20 20:02:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2028-09-22 11:45:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2028-12-21 08:20:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2029-03-20 08:01:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2029-06-21 01:48:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2029-09-22 17:37:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2029-12-21 14:14:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2030-03-20 13:51:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2030-06-21 07:31:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2030-09-22 23:27:00"))
+ SolvervEntry(def: SolvervDef(utcString: "2030-12-21 20:09:00"))
+}
+
+struct SolvervDef {
+ let date: Date;
+
+ init(date:Date) {
+ self.date = date;
+ }
+
+ init(utcString:String) {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
+ formatter.timeZone = TimeZone(abbreviation: "UTC")
+ // Should probably guard this, but not now
+ let date = formatter.date(from: utcString)!
+ self.date = date
+ }
+
+ func emoji() -> String {
+ let components = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute], from: date)
+ let hour = components.hour!
+ let minute = components.minute!
+ if hour == 2 && minute == 43 {
+ return "😀"
+ } else {
+ return ""
+ }
+ }
+}
diff --git a/Solsnu.Widget/Solsnu_WidgetBundle.swift b/Solsnu.Widget/Solsnu_WidgetBundle.swift
new file mode 100644
index 0000000..24e5cbe
--- /dev/null
+++ b/Solsnu.Widget/Solsnu_WidgetBundle.swift
@@ -0,0 +1,17 @@
+//
+// Solsnu_WidgetBundle.swift
+// Solsnu.Widget
+//
+// Created by Ivar Løvlie on 15/12/2025.
+//
+
+import WidgetKit
+import SwiftUI
+
+@main
+struct Solsnu_WidgetBundle: WidgetBundle {
+ var body: some Widget {
+ Solsnu_Widget()
+ Solsnu_WidgetControl()
+ }
+}
diff --git a/Solsnu.Widget/Solsnu_WidgetControl.swift b/Solsnu.Widget/Solsnu_WidgetControl.swift
new file mode 100644
index 0000000..62cd817
--- /dev/null
+++ b/Solsnu.Widget/Solsnu_WidgetControl.swift
@@ -0,0 +1,54 @@
+//
+// Solsnu_WidgetControl.swift
+// Solsnu.Widget
+//
+// Created by Ivar Løvlie on 15/12/2025.
+//
+
+import AppIntents
+import SwiftUI
+import WidgetKit
+
+struct Solsnu_WidgetControl: ControlWidget {
+ var body: some ControlWidgetConfiguration {
+ StaticControlConfiguration(
+ kind: "ivarivarivar.Solverv.Solsnu.Widget",
+ provider: Provider()
+ ) { value in
+ ControlWidgetToggle(
+ "Start Timer",
+ isOn: value,
+ action: StartTimerIntent()
+ ) { isRunning in
+ Label(isRunning ? "On" : "Off", systemImage: "timer")
+ }
+ }
+ .displayName("Timer")
+ .description("A an example control that runs a timer.")
+ }
+}
+
+extension Solsnu_WidgetControl {
+ struct Provider: ControlValueProvider {
+ var previewValue: Bool {
+ false
+ }
+
+ func currentValue() async throws -> Bool {
+ let isRunning = true // Check if the timer is running
+ return isRunning
+ }
+ }
+}
+
+struct StartTimerIntent: SetValueIntent {
+ static let title: LocalizedStringResource = "Start a timer"
+
+ @Parameter(title: "Timer is running")
+ var value: Bool
+
+ func perform() async throws -> some IntentResult {
+ // Start / stop the timer based on `value`.
+ return .result()
+ }
+}