// // ConduitWidget.swift // ConduitWidget // // Created by cogwheel on 07/12/25. // import WidgetKit import SwiftUI // MARK: - Timeline Entry struct ConduitEntry: TimelineEntry { let date: Date } // MARK: - Timeline Provider struct ConduitProvider: TimelineProvider { func placeholder(in context: Context) -> ConduitEntry { ConduitEntry(date: Date()) } func getSnapshot(in context: Context, completion: @escaping (ConduitEntry) -> Void) { let entry = ConduitEntry(date: Date()) completion(entry) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { let entry = ConduitEntry(date: Date()) let timeline = Timeline(entries: [entry], policy: .never) completion(timeline) } } // MARK: - Widget View struct ConduitWidgetEntryView: View { var entry: ConduitProvider.Entry @Environment(\.widgetFamily) var family @Environment(\.colorScheme) var colorScheme /// Adaptive text/icon color based on color scheme private var contentColor: Color { colorScheme == .dark ? .white : .black } /// Adaptive button background based on color scheme private var buttonBackground: Color { colorScheme == .dark ? .white.opacity(0.15) : .black.opacity(0.08) } var body: some View { VStack(spacing: 12) { // Main "Ask Conduit" pill - ChatGPT style Link(destination: URL(string: "conduit://new_chat")!) { HStack(spacing: 12) { Image("HubIcon") .renderingMode(.template) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 28, height: 28) .foregroundStyle(contentColor.opacity(0.85)) Text("Ask Conduit") .font(.system(size: 18, weight: .medium, design: .rounded)) .foregroundStyle(contentColor.opacity(0.85)) Spacer() } .padding(.horizontal, 20) .frame(maxWidth: .infinity) .frame(height: 56) .background( Capsule() .fill(buttonBackground) ) } .buttonStyle(.plain) // 4 circular icon buttons - ChatGPT style, fill width HStack(spacing: 8) { CircularIconButton( symbol: "camera", url: "conduit://camera", contentColor: contentColor, buttonBackground: buttonBackground ) CircularIconButton( symbol: "photo.on.rectangle.angled", url: "conduit://photos", contentColor: contentColor, buttonBackground: buttonBackground ) CircularIconButton( symbol: "waveform", url: "conduit://mic", contentColor: contentColor, buttonBackground: buttonBackground ) CircularIconButton( symbol: "doc.on.clipboard", url: "conduit://clipboard", contentColor: contentColor, buttonBackground: buttonBackground ) } } .padding(16) } } // MARK: - Circular Icon Button (ChatGPT Style) struct CircularIconButton: View { let symbol: String let url: String let contentColor: Color let buttonBackground: Color var body: some View { Link(destination: URL(string: url)!) { Image(systemName: symbol) .font(.system(size: 24, weight: .medium)) .foregroundStyle(contentColor.opacity(0.85)) .frame(maxWidth: .infinity, maxHeight: .infinity) .background( RoundedRectangle(cornerRadius: 16, style: .continuous) .fill(buttonBackground) ) } .buttonStyle(.plain) } } // MARK: - Widget Configuration struct ConduitWidget: Widget { let kind: String = "ConduitWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: ConduitProvider()) { entry in if #available(iOS 17.0, *) { ConduitWidgetEntryView(entry: entry) .containerBackground(Color("WidgetBackground"), for: .widget) } else { ConduitWidgetEntryView(entry: entry) .background(Color("WidgetBackground")) } } .configurationDisplayName("Conduit") .description("Quick access to chat, camera, photos, and voice.") .supportedFamilies([.systemMedium]) .contentMarginsDisabled() } } // MARK: - Preview #Preview(as: .systemMedium) { ConduitWidget() } timeline: { ConduitEntry(date: .now) }