Complete ground-up rewrite in SwiftUI targeting iOS 26. Drops the Flutter/Dart codebase entirely in favour of a lean native app with no third-party dependencies. Features shipped: - Bookmark list with pagination, pull-to-refresh, swipe delete/archive - Add bookmark form + iOS share extension (zero-tap save from any app) - Tags tab — all tags sorted by count, tap to browse filtered bookmarks - Native search tab (Tab role: .search) with instant client-side filtering - AI enrichment via OpenRouter (google/gemini-2.0-flash-lite-001): auto-summary and tag generation, semantic search, smart collections - Settings: linkding server config, OpenRouter API key - App Groups for credential sharing between main app and share extension - Swift 6 strict concurrency throughout (@Observable, @MainActor) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
1.1 KiB
Swift
39 lines
1.1 KiB
Swift
import Foundation
|
|
|
|
struct ServerConfig: Codable, Sendable {
|
|
var host: String
|
|
var port: Int?
|
|
var path: String
|
|
var token: String
|
|
var useHttps: Bool
|
|
|
|
var baseUrl: String {
|
|
var url = useHttps ? "https://" : "http://"
|
|
url += host
|
|
if let port { url += ":\(port)" }
|
|
if !path.isEmpty { url += path }
|
|
return url
|
|
}
|
|
}
|
|
|
|
extension ServerConfig {
|
|
private static let key = "serverConfig"
|
|
private static let appGroupId = "group.com.magicive.marks"
|
|
|
|
static func load() -> ServerConfig? {
|
|
guard let data = UserDefaults.standard.data(forKey: key) else { return nil }
|
|
return try? JSONDecoder().decode(ServerConfig.self, from: data)
|
|
}
|
|
|
|
func save() {
|
|
guard let data = try? JSONEncoder().encode(self) else { return }
|
|
UserDefaults.standard.set(data, forKey: ServerConfig.key)
|
|
UserDefaults(suiteName: ServerConfig.appGroupId)?.set(data, forKey: ServerConfig.key)
|
|
}
|
|
|
|
func delete() {
|
|
UserDefaults.standard.removeObject(forKey: ServerConfig.key)
|
|
UserDefaults(suiteName: ServerConfig.appGroupId)?.removeObject(forKey: ServerConfig.key)
|
|
}
|
|
}
|