Added skills, shortcuts, and bugifixes++
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user