aboutsummaryrefslogtreecommitdiff
path: root/Hotline/Models
diff options
context:
space:
mode:
authorDustin Mierau <dustin@mierau.me>2024-01-17 23:18:27 -0800
committerDustin Mierau <dustin@mierau.me>2024-01-17 23:18:27 -0800
commit1b303803e53dbeb24dab1a7c714d71ee14f002db (patch)
tree4616861b23642d26c9b58b5925315232c1fdb975 /Hotline/Models
parent8e85fbbdadcb993cd270ff4bf60d2280b9e7ad56 (diff)
Added server and tracker bookmarks. Reordering in Servers window. Delete. All stored securely in Keychain.
Diffstat (limited to 'Hotline/Models')
-rw-r--r--Hotline/Models/Bookmarks.swift126
-rw-r--r--Hotline/Models/Hotline.swift67
-rw-r--r--Hotline/Models/Tracker.swift7
3 files changed, 133 insertions, 67 deletions
diff --git a/Hotline/Models/Bookmarks.swift b/Hotline/Models/Bookmarks.swift
new file mode 100644
index 0000000..3f4971c
--- /dev/null
+++ b/Hotline/Models/Bookmarks.swift
@@ -0,0 +1,126 @@
+import SwiftUI
+
+extension NSNotification {
+ static let BookmarkAdded = Notification.Name("BookmarkAdded")
+ static let BookmarkRemoved = Notification.Name("BookmarkRemoved")
+}
+
+enum BookmarkType: String, Codable {
+ case tracker = "tracker"
+ case server = "server"
+}
+
+struct Bookmark: Codable, Equatable {
+ let type: BookmarkType
+ let name: String
+ let address: String
+ let port: Int
+ let login: String?
+ let password: String?
+
+ init(type: BookmarkType, name: String, address: String, port: Int = HotlinePorts.DefaultServerPort, login: String? = nil, password: String? = nil) {
+ self.type = type
+ self.name = name
+ self.address = address
+ self.port = port
+ self.login = login
+ self.password = password
+ }
+}
+
+@Observable final class Bookmarks {
+ var bookmarks: [Bookmark]? = nil
+
+ static let DefaultBookmarks: [Bookmark] = [
+ Bookmark(type: .server, name: "System 7 Today", address: "hotline.system7today.com"),
+ Bookmark(type: .server, name: "The Mobius Strip", address: "67.174.208.111"),
+ Bookmark(type: .tracker, name: "Featured Servers", address: "hltracker.com"),
+ ]
+
+ init() {
+ self.load()
+ }
+
+ func apply(_ newBookmarks: [Bookmark], save shouldSave: Bool = true) {
+ self.bookmarks = newBookmarks
+ if shouldSave {
+ self.save()
+ }
+ }
+
+ func load() {
+ let jsonString: String? = DAKeychain.shared["Hotline Bookmarks"]
+ let jsonData: Data? = jsonString?.data(using: .utf8, allowLossyConversion: false)
+
+ let decoder = JSONDecoder()
+ var decodedBookmarks = try? decoder.decode([Bookmark].self, from: jsonData ?? Data())
+ if decodedBookmarks == nil || decodedBookmarks?.isEmpty == true {
+ print("Bookmarks: using default bookmarks")
+ decodedBookmarks = Bookmarks.DefaultBookmarks
+ }
+ else {
+ print("Bookmarks: using saved bookmarks")
+ }
+
+ self.bookmarks = [Bookmark](decodedBookmarks!)
+ }
+
+ func save() {
+ var bookmarksToSave = self.bookmarks
+ if bookmarksToSave == Bookmarks.DefaultBookmarks {
+ print("Bookmarks: skipping saving default bookmarks")
+ bookmarksToSave = []
+ }
+
+ let encoder = JSONEncoder()
+ encoder.outputFormatting = .prettyPrinted
+ if let jsonData = try? encoder.encode(bookmarksToSave) {
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
+ DAKeychain.shared["Hotline Bookmarks"] = jsonString
+ }
+ }
+ }
+
+ // MARK: -
+
+ func add(_ bookmark: Bookmark, save shouldSave: Bool = true) {
+ self.bookmarks?.insert(bookmark, at: 0)
+
+ if shouldSave {
+ self.save()
+ }
+
+ DispatchQueue.main.async {
+ NotificationCenter.default.post(name: NSNotification.BookmarkAdded, object: nil, userInfo: ["index": 0])
+ }
+ }
+
+ func delete(_ bookmark: Bookmark, save shouldSave: Bool = true) -> Bool {
+ if let i = self.bookmarks?.firstIndex(where: { b in b.address.lowercased() == bookmark.address.lowercased() && b.port == bookmark.port }) {
+ self.bookmarks?.remove(at: i)
+
+ if shouldSave {
+ self.save()
+ }
+
+ DispatchQueue.main.async {
+ NotificationCenter.default.post(name: NSNotification.BookmarkRemoved, object: nil, userInfo: ["index": i])
+ }
+ return true
+ }
+
+ return false
+ }
+
+ func update(_ bookmark: Bookmark, save shouldSave: Bool = true) -> Bool {
+ if let i = self.bookmarks?.firstIndex(where: { b in b.address.lowercased() == bookmark.address.lowercased() && b.port == bookmark.port }) {
+ self.bookmarks?[i] = bookmark
+ if shouldSave {
+ self.save()
+ }
+ return true
+ }
+
+ return false
+ }
+}
diff --git a/Hotline/Models/Hotline.swift b/Hotline/Models/Hotline.swift
index 77d4d59..6b5e3a7 100644
--- a/Hotline/Models/Hotline.swift
+++ b/Hotline/Models/Hotline.swift
@@ -103,73 +103,6 @@ final class Hotline: HotlineClientDelegate, HotlineFileClientDelegate {
6029, 6030, 6031, 6032, 6033, 6034, 6035
]
- static let defaultIconSet: [Int: String] = [
- 414: "๐Ÿ™‚",
- 2000: "๐Ÿ“Ÿ",
- 2001: "๐Ÿ’€",
- 2002: "๐Ÿชฉ",
- 2003: "๐Ÿ’ฅ",
- 2004: "๐Ÿž",
- 2014: "๐ŸŽ",
- 2006: "๐Ÿ’ ",
- 2007: "๐Ÿฆ ",
- 2008: "๐Ÿช€",
- 2009: "๐Ÿ›Ÿ",
- 2010: "๐Ÿ‰",
- 2011: "๐Ÿ",
- 2012: "๐Ÿšฆ",
- 145: "๐Ÿš”",
- 2015: "๐Ÿ‘ป",
- 2016: "๐Ÿ’ป",
- 2017: "โ˜€๏ธ",
- 2018: "โžก๏ธ",
- 417: "๐Ÿงโ€โ™‚๏ธ",
- 140: "๐ŸŽจ",
- 141: "๐Ÿ‘ฝ",
- 142: "๐Ÿš€",
- 143: "๐Ÿ•ท๏ธ",
- 138: "๐Ÿ˜บ",
- 146: "๐ŸŒ…",
- 149: "๐Ÿฎ",
- 150: "๐Ÿฆ–",
- 151: "๐Ÿงป",
- 154: "๐Ÿ–",
- 182: "โœ‹",
- 207: "โš ๏ธ",
- 2061: "โ˜•๏ธ",
- 2063: "๐ŸŒฎ",
- 2064: "๐Ÿ•",
- 2065: "๐Ÿ”",
- 2066: "๐ŸŒญ",
- 2067: "๐Ÿญ",
- 2013: "๐Ÿง",
- 2037: "โš ๏ธ",
- 2055: "โšก๏ธ",
- 2400: "๐Ÿ‡จ๐Ÿ‡ฆ",
- 2036: "โ˜ฃ๏ธ",
- 4134: "๐Ÿฆˆ",
- 4247: "๐Ÿ—",
- 135: "โ˜ฏ๏ธ",
- 137: "๐Ÿ",
- 144: "๐Ÿš€",
- 165: "๐ŸŽถ",
- 166: "โค๏ธ",
- 2549: "๐Ÿ‡ฎ๐Ÿ‡ฑ",
- 2553: "๐Ÿ‡บ๐Ÿ‡ธ",
- 2555: "๐Ÿ‡จ๐Ÿ‡ฆ",
- 2552: "๐Ÿ‡ฎ๐Ÿ‡ณ",
- 2556: "๐Ÿ‡ฆ๐Ÿ‡บ",
- 2565: "๐Ÿ‡ฌ๐Ÿ‡ง",
- 2567: "๐Ÿ‡ฏ๐Ÿ‡ต",
- 2566: "๐Ÿ‡ซ๐Ÿ‡ท",
- 2564: "๐Ÿ‡ฉ๐Ÿ‡ช",
- 2563: "๐Ÿ‡ฎ๐Ÿ‡น",
- 2550: "๐Ÿ‡ญ๐Ÿ‡บ",
- 2551: "๐Ÿ‡ต๐Ÿ‡ฑ",
- 2560: "๐Ÿ‡ช๐Ÿ‡ธ",
- 2561: "๐Ÿ‡ธ๐Ÿ‡ช",
- ]
-
var status: HotlineClientStatus = .disconnected
var server: Server? {
diff --git a/Hotline/Models/Tracker.swift b/Hotline/Models/Tracker.swift
index e9961e9..171cb35 100644
--- a/Hotline/Models/Tracker.swift
+++ b/Hotline/Models/Tracker.swift
@@ -8,4 +8,11 @@ import SwiftUI
self.address = address
self.port = port
}
+
+ static func parseTrackerAddressAndPort(_ address: String) -> (String, Int) {
+ let url = URL(string: "hotlinetracker://\(address)")
+ let port = url?.port ?? HotlinePorts.DefaultTrackerPort
+ let host = url?.host(percentEncoded: false) ?? ""
+ return (host.lowercased().trimmingCharacters(in: .whitespacesAndNewlines), port)
+ }
}