-
-
Save obito/2f750bc0df1f1b2faac350315dc88f88 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// love_letter_widget.swift | |
// love-letter-widget | |
// | |
// Created by youss on 08/06/2023. | |
// | |
import WidgetKit | |
import SwiftUI | |
import Intents | |
import Supabase | |
struct Message: Identifiable, Hashable, Decodable { | |
let id: Int | |
let message: String | |
} | |
struct MessageEntry: TimelineEntry { | |
var message: String | |
var date: Date | |
} | |
struct MessageFetcher { | |
private static var supabase = SupabaseClient(supabaseURL: URL(string: "https://XXX.supabase.co")!, supabaseKey: "XXX") | |
/// The path where the cached message located | |
private static var cachePath: URL { | |
URL.cachesDirectory.appending(path: "message.txt") | |
} | |
/// The cached message | |
static var cachedMessage: String? { | |
guard let message = try? Data(contentsOf: cachePath) else { | |
return nil | |
} | |
return String(decoding: message, as: UTF8.self) | |
} | |
/// Is cached message currently available | |
static var cachedMessageAvailable: Bool { | |
cachedMessage != nil | |
} | |
static func getMessage() async throws -> Message { | |
do { | |
let latestMessage: [Message] = try await supabase.database | |
.from("messages") | |
.select() | |
.order(column: "id", ascending: false) | |
.limit(count: 1) | |
.execute() | |
.value | |
return latestMessage[0] | |
} catch { | |
throw error | |
} | |
} | |
/// Call the Database and then get last message and cache it | |
static func fetchLastMessage() async throws -> Message { | |
// Parse the JSON data | |
let message = try await getMessage() | |
// Spawn another task to cache the downloaded image | |
Task { | |
try? await cache(message.message.data(using: .utf8)!) | |
} | |
return message | |
} | |
/// Save the message locally | |
private static func cache(_ messageData: Data) async throws { | |
try messageData.write(to: cachePath) | |
} | |
} | |
struct Provider: IntentTimelineProvider { | |
func placeholder(in context: Context) -> MessageEntry { | |
MessageEntry(message: "Je t'aime", date: Date()) | |
} | |
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (MessageEntry) -> ()) { | |
var snapshotMessage: String | |
if context.isPreview && !MessageFetcher.cachedMessageAvailable { | |
snapshotMessage = "Je t'aime" | |
} else { | |
snapshotMessage = MessageFetcher.cachedMessage! | |
} | |
let entry = MessageEntry(message: snapshotMessage, date: Date()) | |
completion(entry) | |
} | |
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { | |
Task { | |
// Fetch a random doggy image from server | |
guard let message = try? await MessageFetcher.fetchLastMessage() else { | |
return | |
} | |
let entry = MessageEntry(message: message.message, date: Date()) | |
// Next fetch happens 15 minutes later | |
let nextUpdate = Calendar.current.date( | |
byAdding: DateComponents(minute: 15), | |
to: Date() | |
)! | |
let timeline = Timeline( | |
entries: [entry], | |
policy: .after(nextUpdate) | |
) | |
completion(timeline) | |
} | |
} | |
} | |
struct love_letter_widgetEntryView : View { | |
var entry: Provider.Entry | |
var body: some View { | |
Text(entry.message) | |
} | |
} | |
struct love_letter_widget: Widget { | |
let kind: String = "love_letter_widget" | |
var body: some WidgetConfiguration { | |
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in | |
love_letter_widgetEntryView(entry: entry) | |
} | |
.configurationDisplayName("My Widget") | |
.description("This is an example widget.") | |
} | |
} | |
struct love_letter_widget_Previews: PreviewProvider { | |
static var previews: some View { | |
love_letter_widgetEntryView(entry: MessageEntry(message: "Je t'aime", date: Date())) | |
.previewContext(WidgetPreviewContext(family: .systemSmall)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment