mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-28 15:44:32 +00:00
Improved Timer UI, removed the Tab
This commit is contained in:
parent
d7c8b1ef61
commit
a9f9ac3aa8
14 changed files with 1079 additions and 241 deletions
|
|
@ -196,6 +196,27 @@ enum ProgressBarStyle: String, CaseIterable, Identifiable, Defaults.Serializable
|
|||
var id: String { self.rawValue }
|
||||
}
|
||||
|
||||
enum TimerIconColorMode: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||
case adaptive = "Adaptive"
|
||||
case solid = "Solid"
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .adaptive: return "Adaptive gradient"
|
||||
case .solid: return "Solid colour"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TimerProgressStyle: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||
case bar = "Bar"
|
||||
case ring = "Ring"
|
||||
|
||||
var id: String { rawValue }
|
||||
}
|
||||
|
||||
// AI Model types for screen assistant
|
||||
enum AIModelProvider: String, CaseIterable, Identifiable, Defaults.Serializable {
|
||||
case gemini = "Gemini"
|
||||
|
|
@ -407,6 +428,12 @@ extension Defaults.Keys {
|
|||
|
||||
// MARK: Timer Feature
|
||||
static let enableTimerFeature = Key<Bool>("enableTimerFeature", default: true)
|
||||
static let timerPresets = Key<[TimerPreset]>("timerPresets", default: TimerPreset.defaultPresets)
|
||||
static let timerIconColorMode = Key<TimerIconColorMode>("timerIconColorMode", default: .adaptive)
|
||||
static let timerSolidColor = Key<Color>("timerSolidColor", default: .blue)
|
||||
static let timerShowsCountdown = Key<Bool>("timerShowsCountdown", default: true)
|
||||
static let timerShowsProgress = Key<Bool>("timerShowsProgress", default: true)
|
||||
static let timerProgressStyle = Key<TimerProgressStyle>("timerProgressStyle", default: .bar)
|
||||
|
||||
// MARK: ColorPicker Feature
|
||||
static let enableColorPickerFeature = Key<Bool>("enableColorPickerFeature", default: true)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class DynamicIslandViewModel: NSObject, ObservableObject {
|
|||
@Published var isColorPickerPopoverActive: Bool = false
|
||||
@Published var isStatsPopoverActive: Bool = false
|
||||
@Published var isMediaOutputPopoverActive: Bool = false
|
||||
@Published var isTimerPopoverActive: Bool = false
|
||||
@Published var shouldRecheckHover: Bool = false
|
||||
|
||||
let webcamManager = WebcamManager.shared
|
||||
|
|
|
|||
93
DynamicIsland/models/TimerPreset.swift
Normal file
93
DynamicIsland/models/TimerPreset.swift
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// TimerPreset.swift
|
||||
// DynamicIsland
|
||||
//
|
||||
// Created by GitHub Copilot on 2025-11-01.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
import Defaults
|
||||
|
||||
struct TimerPreset: Identifiable, Codable, Hashable, Defaults.Serializable {
|
||||
struct ColorData: Codable, Hashable, Defaults.Serializable {
|
||||
var red: Double
|
||||
var green: Double
|
||||
var blue: Double
|
||||
var alpha: Double
|
||||
|
||||
init(red: Double, green: Double, blue: Double, alpha: Double = 1.0) {
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.alpha = alpha
|
||||
}
|
||||
|
||||
init(color: Color) {
|
||||
let nsColor = NSColor(color).usingColorSpace(.sRGB) ?? NSColor(color)
|
||||
self.red = nsColor.redComponent
|
||||
self.green = nsColor.greenComponent
|
||||
self.blue = nsColor.blueComponent
|
||||
self.alpha = nsColor.alphaComponent
|
||||
}
|
||||
|
||||
var color: Color {
|
||||
Color(red: red, green: green, blue: blue, opacity: alpha)
|
||||
}
|
||||
}
|
||||
|
||||
struct DurationComponents {
|
||||
var hours: Int
|
||||
var minutes: Int
|
||||
var seconds: Int
|
||||
}
|
||||
|
||||
var id: UUID
|
||||
var name: String
|
||||
var duration: TimeInterval
|
||||
var colorData: ColorData
|
||||
|
||||
init(id: UUID = UUID(), name: String, duration: TimeInterval, colorData: ColorData) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.duration = duration
|
||||
self.colorData = colorData
|
||||
}
|
||||
|
||||
init(id: UUID = UUID(), name: String, duration: TimeInterval, color: Color) {
|
||||
self.init(id: id, name: name, duration: duration, colorData: ColorData(color: color))
|
||||
}
|
||||
|
||||
var color: Color {
|
||||
colorData.color
|
||||
}
|
||||
|
||||
mutating func updateColor(_ newColor: Color) {
|
||||
colorData = ColorData(color: newColor)
|
||||
}
|
||||
|
||||
var formattedDuration: String {
|
||||
let formatter = DateComponentsFormatter()
|
||||
formatter.allowedUnits = duration >= 3600 ? [.hour, .minute, .second] : [.minute, .second]
|
||||
formatter.zeroFormattingBehavior = [.pad]
|
||||
return formatter.string(from: duration) ?? "0:00"
|
||||
}
|
||||
|
||||
static func components(for duration: TimeInterval) -> DurationComponents {
|
||||
let totalSeconds = max(0, Int(duration))
|
||||
let hours = totalSeconds / 3600
|
||||
let minutes = (totalSeconds % 3600) / 60
|
||||
let seconds = totalSeconds % 60
|
||||
return DurationComponents(hours: hours, minutes: minutes, seconds: seconds)
|
||||
}
|
||||
|
||||
static func duration(from components: DurationComponents) -> TimeInterval {
|
||||
TimeInterval(components.hours * 3600 + components.minutes * 60 + components.seconds)
|
||||
}
|
||||
|
||||
static let defaultPresets: [TimerPreset] = [
|
||||
TimerPreset(name: "Focus", duration: 25 * 60, color: Color.orange),
|
||||
TimerPreset(name: "Break", duration: 5 * 60, color: Color.green),
|
||||
TimerPreset(name: "Deep Work", duration: 45 * 60, color: Color.purple)
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue