Working Screen Assistant with snipping

This commit is contained in:
Hariharan Mudaliar 2025-09-22 00:39:40 +05:30
commit 2f7821f4fd
20 changed files with 4007 additions and 2 deletions

View file

@ -49,6 +49,25 @@ enum ClipboardDisplayMode: String, CaseIterable, Codable, Defaults.Serializable
}
}
enum ScreenAssistantDisplayMode: String, CaseIterable, Codable, Defaults.Serializable {
case popover = "popover" // Traditional popover attached to button
case panel = "panel" // Floating panel near notch
var displayName: String {
switch self {
case .popover: return "Popover"
case .panel: return "Panel"
}
}
var description: String {
switch self {
case .popover: return "Shows screen assistant as a dropdown attached to the AI button"
case .panel: return "Shows screen assistant in a floating panel near the notch"
}
}
}
enum ColorPickerDisplayMode: String, CaseIterable, Codable, Defaults.Serializable {
case popover = "popover" // Traditional popover attached to button
case panel = "panel" // Floating panel near notch
@ -105,12 +124,86 @@ enum ProgressBarStyle: String, CaseIterable, Identifiable, Defaults.Serializable
var id: String { self.rawValue }
}
// AI Model types for screen assistant
enum AIModelProvider: String, CaseIterable, Identifiable, Defaults.Serializable {
case gemini = "Gemini"
case openai = "OpenAI GPT"
case claude = "Claude"
case local = "Local Model"
var id: String { self.rawValue }
var displayName: String {
return self.rawValue
}
var description: String {
switch self {
case .gemini: return "Google's Gemini AI with multimodal capabilities"
case .openai: return "OpenAI's GPT models with advanced reasoning"
case .claude: return "Anthropic's Claude with strong analytical skills"
case .local: return "Local AI model (Ollama or similar)"
}
}
var supportedModels: [AIModel] {
switch self {
case .gemini:
return [
// Gemini 2.5 Models (Latest)
AIModel(id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", supportsThinking: true),
AIModel(id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", supportsThinking: true),
AIModel(id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash-Lite", supportsThinking: false),
AIModel(id: "gemini-2.5-flash-live", name: "Gemini 2.5 Flash Live", supportsThinking: false),
AIModel(id: "gemini-2.5-flash-native-audio", name: "Gemini 2.5 Flash Native Audio", supportsThinking: true),
// Gemini 2.0 Models
AIModel(id: "gemini-2.0-flash", name: "Gemini 2.0 Flash", supportsThinking: false),
AIModel(id: "gemini-2.0-flash-lite", name: "Gemini 2.0 Flash-Lite", supportsThinking: false),
AIModel(id: "gemini-2.0-flash-live", name: "Gemini 2.0 Flash Live", supportsThinking: false),
// Legacy 1.5 Models (for compatibility)
AIModel(id: "gemini-1.5-pro", name: "Gemini 1.5 Pro", supportsThinking: false),
AIModel(id: "gemini-1.5-flash", name: "Gemini 1.5 Flash", supportsThinking: false)
]
case .openai:
return [
AIModel(id: "gpt-4o", name: "GPT-4o", supportsThinking: false),
AIModel(id: "gpt-4o-mini", name: "GPT-4o Mini", supportsThinking: false),
AIModel(id: "o1-preview", name: "o1 Preview", supportsThinking: true),
AIModel(id: "o1-mini", name: "o1 Mini", supportsThinking: true)
]
case .claude:
return [
AIModel(id: "claude-3-5-sonnet", name: "Claude 3.5 Sonnet", supportsThinking: false),
AIModel(id: "claude-3-haiku", name: "Claude 3 Haiku", supportsThinking: false)
]
case .local:
return [
AIModel(id: "llama3.2", name: "Llama 3.2", supportsThinking: false),
AIModel(id: "qwen2.5", name: "Qwen 2.5", supportsThinking: false)
]
}
}
}
struct AIModel: Codable, Identifiable, Defaults.Serializable {
let id: String
let name: String
let supportsThinking: Bool
var displayName: String {
return name + (supportsThinking ? " (Thinking)" : "")
}
}
extension Defaults.Keys {
// MARK: General
static let menubarIcon = Key<Bool>("menubarIcon", default: true)
static let showOnAllDisplays = Key<Bool>("showOnAllDisplays", default: false)
static let automaticallySwitchDisplay = Key<Bool>("automaticallySwitchDisplay", default: true)
static let releaseName = Key<String>("releaseName", default: "alpha 0.0.1")
static let hidePanelsFromScreenCapture = Key<Bool>("hideFromScreenCapture", default: false)
// MARK: Behavior
static let minimumHoverDuration = Key<TimeInterval>("minimumHoverDuration", default: 0.3)
@ -228,6 +321,17 @@ extension Defaults.Keys {
static let showClipboardIcon = Key<Bool>("showClipboardIcon", default: true)
static let clipboardDisplayMode = Key<ClipboardDisplayMode>("clipboardDisplayMode", default: .panel)
// MARK: Screen Assistant Feature
static let enableScreenAssistant = Key<Bool>("enableScreenAssistant", default: true)
static let screenAssistantDisplayMode = Key<ScreenAssistantDisplayMode>("screenAssistantDisplayMode", default: .panel)
static let geminiApiKey = Key<String>("geminiApiKey", default: "")
static let openaiApiKey = Key<String>("openaiApiKey", default: "")
static let claudeApiKey = Key<String>("claudeApiKey", default: "")
static let selectedAIProvider = Key<AIModelProvider>("selectedAIProvider", default: .gemini)
static let selectedAIModel = Key<AIModel?>("selectedAIModel", default: nil)
static let enableThinkingMode = Key<Bool>("enableThinkingMode", default: false)
static let localModelEndpoint = Key<String>("localModelEndpoint", default: "http://localhost:11434")
// MARK: Keyboard Shortcuts
static let enableShortcuts = Key<Bool>("enableShortcuts", default: true)