UI/UX Improvements: - Replace SLComposeServiceViewController with custom UIViewController - Add beautiful green-themed UI with Readeck branding and logo - Implement modern card-based layout with shadows and rounded corners - Add custom cancel button and proper navigation styling - Include loading states and comprehensive user feedback Backend Integration: - Add KeychainHelper integration for secure token/endpoint storage - Implement proper API integration with async/await - Add comprehensive error handling and status messages - Include DTOs for API communication Security & Configuration: - Add keychain access groups to entitlements for both main app and extension - Update TokenProvider to save tokens to keychain - Modify LogoutUseCase to clear keychain data - Update SaveServerSettingsUseCase to persist endpoint in keychain - Configure proper build settings and file sharing between targets Extension Lifecycle: - Implement proper URL extraction from various sources - Add automatic extension dismissal on success - Ensure proper extension context handling
73 lines
1.9 KiB
Swift
73 lines
1.9 KiB
Swift
import Foundation
|
|
|
|
protocol TokenProvider {
|
|
func getToken() async -> String?
|
|
func getEndpoint() async -> String?
|
|
func setToken(_ token: String) async
|
|
func clearToken() async
|
|
}
|
|
|
|
class CoreDataTokenProvider: TokenProvider {
|
|
private let settingsRepository = SettingsRepository()
|
|
private var cachedSettings: Settings?
|
|
private var isLoaded = false
|
|
private let keychainHelper = KeychainHelper.shared
|
|
|
|
private func loadSettingsIfNeeded() async {
|
|
guard !isLoaded else { return }
|
|
|
|
do {
|
|
cachedSettings = try await settingsRepository.loadSettings()
|
|
isLoaded = true
|
|
} catch {
|
|
print("Failed to load settings: \(error)")
|
|
cachedSettings = nil
|
|
}
|
|
}
|
|
|
|
func getToken() async -> String? {
|
|
await loadSettingsIfNeeded()
|
|
return cachedSettings?.token
|
|
}
|
|
|
|
func getEndpoint() async -> String? {
|
|
await loadSettingsIfNeeded()
|
|
// Basis-URL ohne /api Suffix, da es in der API-Klasse hinzugefügt wird
|
|
return cachedSettings?.endpoint
|
|
}
|
|
|
|
func setToken(_ token: String) async {
|
|
await loadSettingsIfNeeded()
|
|
|
|
do {
|
|
try await settingsRepository.saveToken(token)
|
|
saveTokenToKeychain(token: token)
|
|
if cachedSettings != nil {
|
|
cachedSettings!.token = token
|
|
}
|
|
} catch {
|
|
print("Failed to save token: \(error)")
|
|
}
|
|
}
|
|
|
|
func clearToken() async {
|
|
do {
|
|
try await settingsRepository.clearSettings()
|
|
cachedSettings = nil
|
|
saveTokenToKeychain(token: "")
|
|
} catch {
|
|
print("Failed to clear settings: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Keychain Support
|
|
|
|
func saveTokenToKeychain(token: String) {
|
|
keychainHelper.saveToken(token)
|
|
}
|
|
|
|
func loadTokenFromKeychain() -> String? {
|
|
keychainHelper.loadToken()
|
|
}
|
|
}
|