aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Models
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2025-10-20 22:15:48 -0700
committerDustin Mierau <dustin@mierau.me>2025-10-20 22:15:48 -0700
commitede41868962ffed386b0da694d14cdfe6cfdb34f (patch)
treef0b91edd1d9c1bbc23de525224b49d6f8e48e815 /Hotline/Models
parent77b3ac3c051fc4e8fa126cd21e261be28f4aad1a (diff)
Cleanup and a bunch of work to fix issues syncing, loading, and general bookmark states in TrackerView. Added search field (substring conjunctive filter on server/bookmark names and descriptions).
Diffstat (limited to 'Hotline/Models')
-rw-r--r--Hotline/Models/ApplicationState.swift16
-rw-r--r--Hotline/Models/Bookmark.swift100
-rw-r--r--Hotline/Models/Preferences.swift134
3 files changed, 38 insertions, 212 deletions
diff --git a/Hotline/Models/ApplicationState.swift b/Hotline/Models/ApplicationState.swift
deleted file mode 100644
index 6e077c5..0000000
--- a/Hotline/Models/ApplicationState.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-import SwiftUI
-
-@Observable
-final class ApplicationState {
- static let shared = ApplicationState()
-
- var activeHotline: Hotline? = nil
- var activeServerState: ServerState? = nil
-
- // Frontmost server window information
- var activeServerID: UUID? = nil
- var activeServerBanner: NSImage? = nil
- var activeServerName: String? = nil
-
- var cloudKitReady: Bool = false
-}
diff --git a/Hotline/Models/Bookmark.swift b/Hotline/Models/Bookmark.swift
index 733a6eb..394f9f6 100644
--- a/Hotline/Models/Bookmark.swift
+++ b/Hotline/Models/Bookmark.swift
@@ -4,7 +4,27 @@ import SwiftData
enum BookmarkType: String, Codable {
case tracker = "tracker"
case server = "server"
- case temporary = "temporary"
+}
+
+struct BookmarkServer: Hashable, Identifiable {
+ let id = UUID()
+ let name: String?
+ let address: String
+ let port: Int
+ let description: String?
+ let users: Int
+
+ var server: Server {
+ Server(name: self.name, description: self.description, address: self.address, port: self.port, users: self.users)
+ }
+
+ init(server: Server) {
+ self.name = server.name
+ self.address = server.address
+ self.port = server.port
+ self.description = server.description
+ self.users = server.users
+ }
}
@Model
@@ -18,29 +38,10 @@ final class Bookmark {
@Attribute(.allowsCloudEncryption)
var login: String?
-
+
@Attribute(.allowsCloudEncryption)
var password: String?
-
- @Attribute(.ephemeral)
- var expanded: Bool = false
-
- @Attribute(.ephemeral)
- var loading: Bool = false
-
- @Attribute(.ephemeral)
- var serverDescription: String? = nil
-
- @Attribute(.ephemeral)
- var serverUserCount: Int? = nil
-
- @Transient
- var servers: [Bookmark] = []
-
- func hash(into hasher: inout Hasher) {
-
- }
-
+
@Transient
var displayAddress: String {
switch self.type {
@@ -51,8 +52,8 @@ final class Bookmark {
else {
return "\(self.address):\(String(self.port))"
}
-
- case .server, .temporary:
+
+ case .server:
if self.port == HotlinePorts.DefaultServerPort {
return self.address
}
@@ -67,9 +68,9 @@ final class Bookmark {
switch self.type {
case .tracker:
return nil
-
- case .server, .temporary:
- return Server(name: self.name, description: self.serverDescription, address: self.address, port: self.port, login: self.login, password: self.password)
+
+ case .server:
+ return Server(name: self.name, description: nil, address: self.address, port: self.port, login: self.login, password: self.password)
}
}
@@ -84,22 +85,11 @@ final class Bookmark {
self.name = name
self.address = address
self.port = port
-
+
self.login = login
self.password = password
}
-
- init(temporaryServer server: Server) {
- self.type = .temporary
-
- self.name = server.name ?? server.address
- self.address = server.address
- self.port = server.port
-
- self.serverDescription = server.description
- self.serverUserCount = server.users
- }
-
+
init?(fileData: Data, name: String? = nil) {
guard fileData.count <= 2000 else {
return nil
@@ -248,11 +238,6 @@ final class Bookmark {
}
static func add(_ bookmark: Bookmark, context: ModelContext) {
- guard bookmark.type != .temporary else {
- print("Bookmark: Attempting to add temporary bookmark to store. Aborting.")
- return
- }
-
let existingBookmarks = Bookmark.fetchAll(context: context)
// Reindex bookmarks before insert.
@@ -348,32 +333,23 @@ final class Bookmark {
}
}
- func fetchServers() async {
+ func fetchServers() async -> [BookmarkServer] {
guard self.type == .tracker else {
- // self.loading = false
- return
- }
-
- DispatchQueue.main.sync {
- self.loading = true
+ return []
}
-
- var fetchedBookmarks: [Bookmark] = []
-
+
+ var fetchedBookmarks: [BookmarkServer] = []
+
let client = HotlineTrackerClient()
if let fetchedServers: [HotlineServer] = try? await client.fetchServers(address: self.address, port: self.port) {
for fetchedServer in fetchedServers {
if let serverName = fetchedServer.name {
let server = Server(name: serverName, description: fetchedServer.description, address: fetchedServer.address, port: Int(fetchedServer.port), users: Int(fetchedServer.users))
- fetchedBookmarks.append(Bookmark(temporaryServer: server))
+ fetchedBookmarks.append(BookmarkServer(server: server))
}
}
}
-
- let newServers = fetchedBookmarks
- DispatchQueue.main.sync {
- self.servers = newServers
- self.loading = false
- }
+
+ return fetchedBookmarks
}
}
diff --git a/Hotline/Models/Preferences.swift b/Hotline/Models/Preferences.swift
deleted file mode 100644
index 207ce91..0000000
--- a/Hotline/Models/Preferences.swift
+++ /dev/null
@@ -1,134 +0,0 @@
-import SwiftUI
-
-enum PrefsKeys: String {
- case username = "username"
- case userIconID = "user icon id"
- case refusePrivateMessages = "refuse private messages"
- case refusePrivateChat = "refuse private chat"
- case enableAutomaticMessage = "enable automatic message"
- case automaticMessage = "automatic message"
- case playSounds = "play sounds"
- case playChatSound = "play chat sound"
- case playFileTransferCompleteSound = "play file transfer complete sound"
- case playPrivateMessageSound = "play private message sound"
- case playJoinSound = "play join sound"
- case playLeaveSound = "play leave sound"
- case playLoggedInSound = "play logged in sound"
- case playErrorSound = "play error sound"
- case playChatInvitationSound = "play chat invitation sound"
- case showBannerToolbar = "show banner toolbar"
- case showJoinLeaveMessages = "show join leave messages"
-}
-
-@Observable
-class Prefs {
- init() {
- UserDefaults.standard.register(defaults:[
- PrefsKeys.username.rawValue: "guest",
- PrefsKeys.userIconID.rawValue: 191,
- PrefsKeys.refusePrivateMessages.rawValue: false,
- PrefsKeys.refusePrivateChat.rawValue: false,
- PrefsKeys.enableAutomaticMessage.rawValue: false,
- PrefsKeys.automaticMessage.rawValue: "",
- PrefsKeys.playSounds.rawValue: true,
- PrefsKeys.playChatSound.rawValue: true,
- PrefsKeys.playFileTransferCompleteSound.rawValue: true,
- PrefsKeys.playPrivateMessageSound.rawValue: true,
- PrefsKeys.playJoinSound.rawValue: true,
- PrefsKeys.playLeaveSound.rawValue: true,
- PrefsKeys.playLoggedInSound.rawValue: true,
- PrefsKeys.playErrorSound.rawValue: true,
- PrefsKeys.playChatInvitationSound.rawValue: true,
- PrefsKeys.showBannerToolbar.rawValue: true,
- PrefsKeys.showJoinLeaveMessages.rawValue: true,
- ])
-
- self.username = UserDefaults.standard.string(forKey: PrefsKeys.username.rawValue)!
- self.userIconID = UserDefaults.standard.integer(forKey: PrefsKeys.userIconID.rawValue)
- self.refusePrivateMessages = UserDefaults.standard.bool(forKey: PrefsKeys.refusePrivateMessages.rawValue)
- self.refusePrivateChat = UserDefaults.standard.bool(forKey: PrefsKeys.refusePrivateChat.rawValue)
- self.enableAutomaticMessage = UserDefaults.standard.bool(forKey: PrefsKeys.enableAutomaticMessage.rawValue)
- self.automaticMessage = UserDefaults.standard.string(forKey: PrefsKeys.automaticMessage.rawValue)!
- self.playSounds = UserDefaults.standard.bool(forKey: PrefsKeys.playSounds.rawValue)
- self.playChatSound = UserDefaults.standard.bool(forKey: PrefsKeys.playChatSound.rawValue)
- self.playFileTransferCompleteSound = UserDefaults.standard.bool(forKey: PrefsKeys.playFileTransferCompleteSound.rawValue)
- self.playPrivateMessageSound = UserDefaults.standard.bool(forKey: PrefsKeys.playPrivateMessageSound.rawValue)
- self.playJoinSound = UserDefaults.standard.bool(forKey: PrefsKeys.playJoinSound.rawValue)
- self.playLeaveSound = UserDefaults.standard.bool(forKey: PrefsKeys.playLeaveSound.rawValue)
- self.playLoggedInSound = UserDefaults.standard.bool(forKey: PrefsKeys.playLoggedInSound.rawValue)
- self.playErrorSound = UserDefaults.standard.bool(forKey: PrefsKeys.playErrorSound.rawValue)
- self.playChatInvitationSound = UserDefaults.standard.bool(forKey: PrefsKeys.playChatInvitationSound.rawValue)
- self.showBannerToolbar = UserDefaults.standard.bool(forKey: PrefsKeys.showBannerToolbar.rawValue)
- self.showJoinLeaveMessages = UserDefaults.standard.bool(forKey: PrefsKeys.showJoinLeaveMessages.rawValue)
- }
-
- public static let shared = Prefs()
-
- var username: String {
- didSet { UserDefaults.standard.set(self.username, forKey: PrefsKeys.username.rawValue) }
- }
-
- var userIconID: Int {
- didSet { UserDefaults.standard.set(self.userIconID, forKey: PrefsKeys.userIconID.rawValue) }
- }
-
- var refusePrivateMessages: Bool {
- didSet { UserDefaults.standard.set(self.refusePrivateMessages, forKey: PrefsKeys.refusePrivateMessages.rawValue) }
- }
-
- var playSounds: Bool {
- didSet { UserDefaults.standard.set(self.playSounds, forKey: PrefsKeys.playSounds.rawValue) }
- }
-
- var playChatSound: Bool {
- didSet { UserDefaults.standard.set(self.playChatSound, forKey: PrefsKeys.playChatSound.rawValue) }
- }
-
- var playFileTransferCompleteSound: Bool {
- didSet { UserDefaults.standard.set(self.playFileTransferCompleteSound, forKey: PrefsKeys.playFileTransferCompleteSound.rawValue) }
- }
-
- var playPrivateMessageSound: Bool {
- didSet { UserDefaults.standard.set(self.playPrivateMessageSound, forKey: PrefsKeys.playPrivateMessageSound.rawValue) }
- }
-
- var playJoinSound: Bool {
- didSet { UserDefaults.standard.set(self.playJoinSound, forKey: PrefsKeys.playJoinSound.rawValue) }
- }
-
- var playLeaveSound: Bool {
- didSet { UserDefaults.standard.set(self.playLeaveSound, forKey: PrefsKeys.playLeaveSound.rawValue) }
- }
-
- var playLoggedInSound: Bool {
- didSet { UserDefaults.standard.set(self.playLoggedInSound, forKey: PrefsKeys.playLoggedInSound.rawValue) }
- }
-
- var playErrorSound: Bool {
- didSet { UserDefaults.standard.set(self.playErrorSound, forKey: PrefsKeys.playErrorSound.rawValue) }
- }
-
- var playChatInvitationSound: Bool {
- didSet { UserDefaults.standard.set(self.playChatInvitationSound, forKey: PrefsKeys.playChatInvitationSound.rawValue) }
- }
-
- var refusePrivateChat: Bool {
- didSet { UserDefaults.standard.set(self.refusePrivateChat, forKey: PrefsKeys.refusePrivateChat.rawValue) }
- }
-
- var enableAutomaticMessage: Bool {
- didSet { UserDefaults.standard.set(self.enableAutomaticMessage, forKey: PrefsKeys.enableAutomaticMessage.rawValue) }
- }
-
- var automaticMessage: String {
- didSet { UserDefaults.standard.set(self.automaticMessage, forKey: PrefsKeys.automaticMessage.rawValue) }
- }
-
- var showBannerToolbar: Bool {
- didSet { UserDefaults.standard.set(self.showBannerToolbar, forKey: PrefsKeys.showBannerToolbar.rawValue) }
- }
-
- var showJoinLeaveMessages: Bool {
- didSet { UserDefaults.standard.set(self.showJoinLeaveMessages, forKey: PrefsKeys.showJoinLeaveMessages.rawValue) }
- }
-}