Files
LockInBroMobile/LockInBroWidget/LockInBroWidgetLiveActivity.swift

121 lines
4.8 KiB
Swift
Raw Permalink Normal View History

//
// LockInBroWidgetLiveActivity.swift
// LockInBroWidget
//
import ActivityKit
import WidgetKit
import SwiftUI
struct LockInBroWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: FocusSessionAttributes.self) { context in
// Lock screen/banner UI
VStack(alignment: .leading, spacing: 6) {
HStack {
Image(systemName: "clock.fill")
.foregroundStyle(.blue)
Text("Focus Mode")
.font(.headline)
.fontWeight(.bold)
Spacer()
Text(Date(timeIntervalSince1970: TimeInterval(context.state.startedAt)), style: .timer)
.font(.title3.monospacedDigit())
.foregroundStyle(.blue)
.multilineTextAlignment(.trailing)
}
Text(context.state.taskTitle)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(1)
if context.state.stepsTotal > 0 {
HStack(spacing: 6) {
ProgressView(value: Double(context.state.stepsCompleted), total: Double(context.state.stepsTotal))
.tint(.blue)
Text("\(context.state.stepsCompleted)/\(context.state.stepsTotal)")
.font(.caption2.monospacedDigit())
.foregroundStyle(.secondary)
}
if let step = context.state.currentStepTitle {
Text("Now: \(step)")
.font(.caption)
.foregroundStyle(.white.opacity(0.7))
.lineLimit(1)
}
}
}
.padding()
.activityBackgroundTint(Color.black.opacity(0.8))
.activitySystemActionForegroundColor(Color.white)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI
DynamicIslandExpandedRegion(.leading) {
Label("Focus", systemImage: "clock.fill")
.font(.caption)
.foregroundStyle(.blue)
}
DynamicIslandExpandedRegion(.trailing) {
Text(Date(timeIntervalSince1970: TimeInterval(context.state.startedAt)), style: .timer)
.font(.caption.monospacedDigit())
.foregroundStyle(.blue)
}
DynamicIslandExpandedRegion(.center) {
Text(context.state.taskTitle)
.font(.subheadline)
.lineLimit(1)
}
DynamicIslandExpandedRegion(.bottom) {
if context.state.stepsTotal > 0 {
Text("\(context.state.stepsCompleted)/\(context.state.stepsTotal) steps — \(context.state.currentStepTitle ?? "Stay locked in!")")
.font(.caption2)
.foregroundStyle(.secondary)
.lineLimit(1)
} else {
Text("Stay locked in!")
.font(.caption2)
.foregroundStyle(.secondary)
}
}
} compactLeading: {
Image(systemName: "clock.fill")
.foregroundStyle(.blue)
} compactTrailing: {
Text(Date(timeIntervalSince1970: TimeInterval(context.state.startedAt)), style: .timer)
.font(.caption2.monospacedDigit())
.frame(maxWidth: 40)
} minimal: {
Image(systemName: "clock.fill")
.foregroundStyle(.blue)
}
.widgetURL(URL(string: "lockinbro://resume-session"))
.keylineTint(Color.blue)
}
}
}
extension FocusSessionAttributes {
fileprivate static var preview: FocusSessionAttributes {
FocusSessionAttributes(sessionType: "Focus")
}
}
extension FocusSessionAttributes.ContentState {
fileprivate static var dummy: FocusSessionAttributes.ContentState {
FocusSessionAttributes.ContentState(
taskTitle: "Finish Physics Assignment",
startedAt: Int(Date().addingTimeInterval(-120).timeIntervalSince1970),
stepsCompleted: 2,
stepsTotal: 5,
currentStepTitle: "Solve problem set 3"
)
}
}
#Preview("Notification", as: .content, using: FocusSessionAttributes.preview) {
LockInBroWidgetLiveActivity()
} contentStates: {
FocusSessionAttributes.ContentState.dummy
}