Added skills, shortcuts, and bugifixes++

This commit is contained in:
2026-02-18 11:58:45 +01:00
parent 09463d7620
commit 54a8c47df4
24 changed files with 3172 additions and 239 deletions

View File

@@ -39,12 +39,6 @@ struct SettingsView: View {
@State private var syncTestResult: String?
@State private var isSyncing = false
// OAuth state
@State private var oauthCode = ""
@State private var oauthError: String?
@State private var showOAuthCodeField = false
private var oauthService = AnthropicOAuthService.shared
// Email handler state
@State private var showEmailLog = false
@State private var showEmailModelSelector = false
@@ -98,6 +92,8 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
Text("Advanced").tag(3)
Text("Sync").tag(4)
Text("Email").tag(5)
Text("Shortcuts").tag(6)
Text("Skills").tag(7)
}
.pickerStyle(.segmented)
.padding(.horizontal, 24)
@@ -120,6 +116,10 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
syncTab
case 5:
emailTab
case 6:
shortcutsTab
case 7:
agentSkillsTab
default:
generalTab
}
@@ -179,75 +179,15 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
ProviderRegistry.shared.clearCache()
}
}
// Anthropic: OAuth or API key
// Anthropic: API key
row("Anthropic") {
VStack(alignment: .leading, spacing: 8) {
if oauthService.isAuthenticated {
// Logged in via OAuth
HStack(spacing: 8) {
Image(systemName: "checkmark.circle.fill")
.foregroundStyle(.green)
Text("Logged in via Claude Pro/Max")
.font(.system(size: 14))
Spacer()
Button("Logout") {
oauthService.logout()
ProviderRegistry.shared.clearCache()
}
.font(.system(size: 14))
.foregroundStyle(.red)
}
} else if showOAuthCodeField {
// Waiting for code paste
HStack(spacing: 8) {
TextField("Paste authorization code...", text: $oauthCode)
.textFieldStyle(.roundedBorder)
Button("Submit") {
Task { await submitOAuthCode() }
}
.disabled(oauthCode.isEmpty || oauthService.isLoggingIn)
Button("Cancel") {
showOAuthCodeField = false
oauthCode = ""
oauthError = nil
}
.font(.system(size: 14))
}
if let error = oauthError {
Text(error)
.font(.system(size: 13))
.foregroundStyle(.red)
}
} else {
// Login button + API key field
HStack(spacing: 8) {
Button {
startOAuthLogin()
} label: {
HStack(spacing: 4) {
Image(systemName: "person.circle")
Text("Login with Claude Pro/Max")
}
.font(.system(size: 14))
}
.buttonStyle(.borderedProminent)
.controlSize(.small)
Text("or")
.font(.system(size: 13))
.foregroundStyle(.secondary)
}
SecureField("sk-ant-... (API key)", text: $anthropicKey)
.textFieldStyle(.roundedBorder)
.onAppear { anthropicKey = settingsService.anthropicAPIKey ?? "" }
.onChange(of: anthropicKey) {
settingsService.anthropicAPIKey = anthropicKey.isEmpty ? nil : anthropicKey
ProviderRegistry.shared.clearCache()
}
SecureField("sk-ant-... (API key)", text: $anthropicKey)
.textFieldStyle(.roundedBorder)
.onAppear { anthropicKey = settingsService.anthropicAPIKey ?? "" }
.onChange(of: anthropicKey) {
settingsService.anthropicAPIKey = anthropicKey.isEmpty ? nil : anthropicKey
ProviderRegistry.shared.clearCache()
}
}
.frame(width: 400, alignment: .leading)
}
row("OpenAI") {
SecureField("sk-...", text: $openaiKey)
@@ -531,6 +471,8 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
// Anytype integration UI hidden (work in progress see AnytypeMCPService.swift)
}
// MARK: - Appearance Tab
@@ -1742,6 +1684,20 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
}
}
// MARK: - Shortcuts Tab
@ViewBuilder
private var shortcutsTab: some View {
ShortcutsTabContent()
}
// MARK: - Agent Skills Tab
@ViewBuilder
private var agentSkillsTab: some View {
AgentSkillsTabContent()
}
// MARK: - Layout Helpers
private func sectionHeader(_ title: String) -> some View {
@@ -1820,32 +1776,6 @@ It's better to admit "I need more information" or "I cannot do that" than to fak
isTestingEmailConnection = false
}
// MARK: - OAuth Helpers
private func startOAuthLogin() {
let url = oauthService.generateAuthorizationURL()
#if os(macOS)
NSWorkspace.shared.open(url)
#endif
showOAuthCodeField = true
oauthError = nil
oauthCode = ""
}
private func submitOAuthCode() async {
oauthService.isLoggingIn = true
oauthError = nil
do {
try await oauthService.exchangeCode(oauthCode)
showOAuthCodeField = false
oauthCode = ""
ProviderRegistry.shared.clearCache()
} catch {
oauthError = error.localizedDescription
}
oauthService.isLoggingIn = false
}
// MARK: - Sync Helpers
private func testSyncConnection() async {