diff options
| author | Dustin Mierau <dustin@mierau.me> | 2025-10-21 10:17:23 -0700 |
|---|---|---|
| committer | Dustin Mierau <dustin@mierau.me> | 2025-10-21 10:17:23 -0700 |
| commit | 926c92be7a32e374c8855b2eb8b5a49485dec072 (patch) | |
| tree | 546d09d4b8c0e29a296fca93c8393cf9b2e18832 /Hotline | |
| parent | ede41868962ffed386b0da694d14cdfe6cfdb34f (diff) | |
Add bookmark editing to TrackerView (you can add login/pass to bookmarks now). Fix macOS 26 border around images in toolbar.
Diffstat (limited to 'Hotline')
| -rw-r--r-- | Hotline/Models/Bookmark.swift | 2 | ||||
| -rw-r--r-- | Hotline/macOS/ServerView.swift | 26 | ||||
| -rw-r--r-- | Hotline/macOS/TrackerView.swift | 205 |
3 files changed, 167 insertions, 66 deletions
diff --git a/Hotline/Models/Bookmark.swift b/Hotline/Models/Bookmark.swift index 394f9f6..80963f9 100644 --- a/Hotline/Models/Bookmark.swift +++ b/Hotline/Models/Bookmark.swift @@ -75,7 +75,7 @@ final class Bookmark { } static let DefaultBookmarks: [Bookmark] = [ - Bookmark(type: .server, name: "The Mobius Strip", address: "67.174.208.111", port: HotlinePorts.DefaultServerPort), + Bookmark(type: .server, name: "The Mobius Strip", address: "24.6.82.54", port: HotlinePorts.DefaultServerPort), Bookmark(type: .server, name: "System 7 Today", address: "hotline.system7today.com", port: HotlinePorts.DefaultServerPort), Bookmark(type: .tracker, name: "Featured Servers", address: "hltracker.com", port: HotlinePorts.DefaultTrackerPort) ] diff --git a/Hotline/macOS/ServerView.swift b/Hotline/macOS/ServerView.swift index e9f4a96..154bd7c 100644 --- a/Hotline/macOS/ServerView.swift +++ b/Hotline/macOS/ServerView.swift @@ -212,14 +212,24 @@ struct ServerView: View { .onChange(of: Prefs.shared.enableAutomaticMessage) { sendPreferences() } .onChange(of: Prefs.shared.automaticMessage) { sendPreferences() } .toolbar { - ToolbarItem(placement: .navigation) { - Image("Server Large") -// .renderingMode(.template) - - .resizable() - .scaledToFit() - .frame(width: 28) - .opacity(controlActiveState == .inactive ? 0.4 : 1.0) + if #available(macOS 26.0, *) { + ToolbarItem(placement: .navigation) { + Image("Server Large") + .resizable() + .scaledToFit() + .frame(width: 28) + .opacity(controlActiveState == .inactive ? 0.4 : 1.0) + } + .sharedBackgroundVisibility(.hidden) + } + else { + ToolbarItem(placement: .navigation) { + Image("Server Large") + .resizable() + .scaledToFit() + .frame(width: 28) + .opacity(controlActiveState == .inactive ? 0.4 : 1.0) + } } } } diff --git a/Hotline/macOS/TrackerView.swift b/Hotline/macOS/TrackerView.swift index 2fbce85..83a56b8 100644 --- a/Hotline/macOS/TrackerView.swift +++ b/Hotline/macOS/TrackerView.swift @@ -24,6 +24,7 @@ struct TrackerView: View { @State private var refreshing = false @State private var trackerSheetPresented: Bool = false @State private var trackerSheetBookmark: Bookmark? = nil + @State private var serverSheetBookmark: Bookmark? = nil @State private var attemptedPrepopulate: Bool = false @State private var fileDropActive = false @State private var bookmarkExportActive = false @@ -270,22 +271,21 @@ struct TrackerView: View { .sheet(isPresented: $trackerSheetPresented) { TrackerBookmarkSheet() } + .sheet(item: $serverSheetBookmark) { item in + ServerBookmarkSheet(item) + } .navigationTitle("Servers") .toolbar { - ToolbarItem(placement: .navigation) { - let image = Image("Hotline") - .resizable() - .renderingMode(.template) - .scaledToFit() - .foregroundColor(Color(hex: 0xE10000)) - .frame(width: 9) - .opacity(controlActiveState == .inactive ? 0.5 : 1.0) - -// if #available(macOS 26, *) { -// image.sharedBackgroundVisibility(.hidden) -// } else { - image -// } + if #available(macOS 26.0, *) { + ToolbarItem(placement: .navigation) { + self.hotlineLogoImage + } + .sharedBackgroundVisibility(.hidden) + } + else { + ToolbarItem(placement: .navigation) { + self.hotlineLogoImage + } } ToolbarItem(placement: .primaryAction) { @@ -326,6 +326,16 @@ struct TrackerView: View { .searchable(text: $searchText, placement: .automatic, prompt: "Search") } + private var hotlineLogoImage: some View { + Image("Hotline") + .resizable() + .renderingMode(.template) + .scaledToFit() + .foregroundColor(Color(hex: 0xE10000)) + .frame(width: 9) + .opacity(controlActiveState == .inactive ? 0.5 : 1.0) + } + @ViewBuilder func bookmarkServerContextMenu(_ server: BookmarkServer) -> some View { Button { @@ -368,10 +378,16 @@ struct TrackerView: View { if bookmark.type == .server { Button { + serverSheetBookmark = bookmark + } label: { + Label("Edit Bookmark...", systemImage: "pencil") + } + + Button { bookmarkExport = BookmarkDocument(bookmark: bookmark) bookmarkExportActive = true } label: { - Label("Export Bookmark...", systemImage: "bookmark.square") + Label("Export Bookmark...", systemImage: "square.and.arrow.down") } } @@ -481,9 +497,12 @@ struct TrackerBookmarkSheet: View { var body: some View { VStack(alignment: .leading) { - Text("Type the address and name of a Hotline Tracker:") - .foregroundStyle(.secondary) - .padding(.bottom, 8) + if self.bookmark == nil { + Text("Type the address and name of a Hotline Tracker:") + .foregroundStyle(.secondary) + .padding(.bottom, 8) + } + Form { Group { TextField(text: $trackerAddress) { @@ -502,33 +521,14 @@ struct TrackerBookmarkSheet: View { .padding() .toolbar { ToolbarItem(placement: .confirmationAction) { - Button(self.bookmark != nil ? "Save Tracker" : "Add Tracker") { - var displayName = trackerName.trimmingCharacters(in: .whitespacesAndNewlines) - let (host, port) = Tracker.parseTrackerAddressAndPort(trackerAddress) - - if displayName.isEmpty { - displayName = host + Button { + self.saveTracker() + } label: { + if self.bookmark != nil { + Text("Save Tracker") } - - if !displayName.isEmpty && !host.isEmpty { - if !host.isEmpty { - if self.bookmark != nil { - // We're editing an existing bookmark. - self.bookmark?.name = displayName - self.bookmark?.address = host - self.bookmark?.port = port - } - else { - // We're creating a new bookmark. - let newBookmark = Bookmark(type: .tracker, name: displayName, address: host, port: port) - Bookmark.add(newBookmark, context: modelContext) - } - - self.trackerName = "" - self.trackerAddress = "" - - dismiss() - } + else { + Text("Add Tracker") } } } @@ -537,7 +537,109 @@ struct TrackerBookmarkSheet: View { self.trackerName = "" self.trackerAddress = "" - dismiss() + self.dismiss() + } + } + } + } + + private func saveTracker() { + var displayName = trackerName.trimmingCharacters(in: .whitespacesAndNewlines) + let (host, port) = Tracker.parseTrackerAddressAndPort(trackerAddress) + + if displayName.isEmpty { + displayName = host + } + + if !displayName.isEmpty && !host.isEmpty { + if !host.isEmpty { + if self.bookmark != nil { + // We're editing an existing bookmark. + self.bookmark?.name = displayName + self.bookmark?.address = host + self.bookmark?.port = port + } + else { + // We're creating a new bookmark. + let newBookmark = Bookmark(type: .tracker, name: displayName, address: host, port: port) + Bookmark.add(newBookmark, context: modelContext) + } + + self.trackerName = "" + self.trackerAddress = "" + + self.dismiss() + } + } + } +} + +struct ServerBookmarkSheet: View { + @Environment(\.dismiss) private var dismiss + @Environment(\.modelContext) private var modelContext + + @State private var bookmark: Bookmark + @State private var serverName: String = "" + @State private var serverAddress: String = "" + @State private var serverLogin: String = "" + @State private var serverPassword: String = "" + + init(_ editingBookmark: Bookmark) { + _bookmark = .init(initialValue: editingBookmark) + _serverName = .init(initialValue: editingBookmark.name) + _serverAddress = .init(initialValue: editingBookmark.displayAddress) + _serverLogin = .init(initialValue: editingBookmark.login ?? "") + _serverPassword = .init(initialValue: editingBookmark.password ?? "") + } + + var body: some View { + VStack(alignment: .leading) { + Form { + Group { + TextField(text: $serverName) { + Text("Name:") + } + .padding(.bottom) + + TextField(text: $serverAddress) { + Text("Address:") + } + TextField(text: $serverLogin, prompt: Text("Optional")) { + Text("Login:") + } + SecureField(text: $serverPassword, prompt: Text("Optional")) { + Text("Password:") + } + } + .textFieldStyle(.roundedBorder) + .controlSize(.large) + } + } + .frame(width: 300) + .fixedSize(horizontal: true, vertical: true) + .padding() + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button("Save Bookmark") { + let displayName = self.serverName.trimmingCharacters(in: .whitespacesAndNewlines) + let (host, port) = Server.parseServerAddressAndPort(self.serverAddress) + let login = self.serverLogin.trimmingCharacters(in: .whitespacesAndNewlines) + let password = self.serverPassword + + if !displayName.isEmpty && !host.isEmpty { + self.bookmark.name = displayName + self.bookmark.address = host + self.bookmark.port = port + self.bookmark.login = login.isEmpty ? nil : login + self.bookmark.password = password.isEmpty ? nil : password + + self.dismiss() + } + } + } + ToolbarItem(placement: .cancellationAction) { + Button("Cancel") { + self.dismiss() } } } @@ -575,7 +677,7 @@ struct TrackerBookmarkServerView: View { content.opacity(opacity) } keyframes: { _ in CubicKeyframe(1.0, duration: 2.0) // Stay visible for 1 second - CubicKeyframe(0.75, duration: 0.5) // Fade out quickly + CubicKeyframe(0.6, duration: 0.5) // Fade out quickly CubicKeyframe(1.0, duration: 0.5) // Fade in quickly } .padding(.trailing, 6) @@ -640,17 +742,6 @@ struct TrackerItemView: View { } } .frame(maxWidth: .infinity, maxHeight: .infinity) -// .onChange(of: self.isExpanded) { -// guard bookmark.type == .tracker else { -// return -// } -// -// if self.isExpanded { -// Task { -// await bookmark.fetchServers() -// } -// } -// } } } |