Rocket.Chat.ReactNative/ios/RocketChat Watch App/Database/Database.swift

133 lines
3.2 KiB
Swift
Raw Permalink Normal View History

2024-04-26 20:33:11 +00:00
import CoreData
import Foundation
protocol ServersDatabase {
var viewContext: NSManagedObjectContext { get }
func server(url: URL) -> Server?
func user(id: String) -> LoggedUser?
func servers() -> [Server]
func remove(_ server: Server)
func save()
func process(updatedServer: WatchMessage.Server)
}
final class DefaultDatabase: ServersDatabase {
private let container: NSPersistentContainer
var viewContext: NSManagedObjectContext {
container.viewContext
}
private static let model: NSManagedObjectModel = {
guard let url = Bundle.main.url(forResource: "Default", withExtension: "momd"),
let managedObjectModel = NSManagedObjectModel(contentsOf: url) else {
fatalError("Can't find Core Data Model")
}
return managedObjectModel
}()
init() {
container = NSPersistentContainer(name: "default", managedObjectModel: Self.model)
container.loadPersistentStores { _, error in
if let error { fatalError("Can't load persistent stores: \(error)") }
}
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
func save() {
guard container.viewContext.hasChanges else {
return
}
try? container.viewContext.save()
}
func server(url: URL) -> Server? {
let request = Server.fetchRequest()
request.predicate = NSPredicate(format: "url == %@", url.absoluteString.removeTrailingSlash())
return try? viewContext.fetch(request).first
}
func user(id: String) -> LoggedUser? {
let request = LoggedUser.fetchRequest()
request.predicate = NSPredicate(format: "id == %@", id)
return try? viewContext.fetch(request).first
}
func servers() -> [Server] {
let request = Server.fetchRequest()
return (try? viewContext.fetch(request)) ?? []
}
func remove(_ server: Server) {
viewContext.delete(server)
save()
}
func process(updatedServer: WatchMessage.Server) {
if let server = server(url: updatedServer.url) {
server.url = updatedServer.url
server.name = updatedServer.name
server.iconURL = updatedServer.iconURL
server.useRealName = updatedServer.useRealName
server.loggedUser = user(from: updatedServer.loggedUser)
server.certificate = updatedServer.clientSSL?.certificate
server.password = updatedServer.clientSSL?.password
server.version = updatedServer.version
} else {
Server(
context: viewContext,
iconURL: updatedServer.iconURL,
name: updatedServer.name,
url: updatedServer.url,
useRealName: updatedServer.useRealName,
loggedUser: user(from: updatedServer.loggedUser),
certificate: updatedServer.clientSSL?.certificate,
password: updatedServer.clientSSL?.password,
version: updatedServer.version
)
}
save()
}
private func user(from updatedUser: WatchMessage.Server.LoggedUser) -> LoggedUser {
if let user = user(id: updatedUser.id) {
user.name = updatedUser.name
user.username = updatedUser.username
user.token = updatedUser.token
return user
}
return LoggedUser(
context: viewContext,
id: updatedUser.id,
name: updatedUser.name,
token: updatedUser.token,
username: updatedUser.username
)
}
}
extension String {
func removeTrailingSlash() -> String {
var url = self
if (url.last == "/") {
url.removeLast()
}
return url
}
}