diff options
Diffstat (limited to 'Hotline/macOS/TrackerView.swift')
| -rw-r--r-- | Hotline/macOS/TrackerView.swift | 181 |
1 files changed, 93 insertions, 88 deletions
diff --git a/Hotline/macOS/TrackerView.swift b/Hotline/macOS/TrackerView.swift index 1382200..0943d63 100644 --- a/Hotline/macOS/TrackerView.swift +++ b/Hotline/macOS/TrackerView.swift @@ -1,6 +1,6 @@ -import SwiftUI -import SwiftData import Foundation +import SwiftData +import SwiftUI import UniformTypeIdentifiers struct TrackerView: View { @@ -8,7 +8,7 @@ struct TrackerView: View { @Environment(\.openWindow) private var openWindow @Environment(\.controlActiveState) private var controlActiveState @Environment(\.modelContext) private var modelContext - + @State private var refreshing = false @State private var trackerSheetPresented: Bool = false @State private var trackerSheetBookmark: Bookmark? = nil @@ -16,7 +16,7 @@ struct TrackerView: View { @State private var fileDropActive = false @State private var bookmarkExportActive = false @State private var bookmarkExport: BookmarkDocument? = nil - + @Query(sort: \Bookmark.order) private var bookmarks: [Bookmark] @Binding var selection: Bookmark? @@ -32,7 +32,7 @@ struct TrackerView: View { } } .tag(bookmark) - + if bookmark.type == .tracker && bookmark.expanded { ForEach(bookmark.servers, id: \.self) { trackedServer in TrackerItemView(bookmark: trackedServer) @@ -51,7 +51,8 @@ struct TrackerView: View { } .onDeleteCommand { if let bookmark = selection, - bookmark.type != .temporary { + bookmark.type != .temporary + { Bookmark.delete(bookmark, context: modelContext) } } @@ -63,40 +64,42 @@ struct TrackerView: View { print("Tracker: Already attempted to prepopulate bookmarks") return } - + print("Tracker: Prepopulating bookmarks") - + attemptedPrepopulate = true - + // Make sure default bookmarks are there when empty. Bookmark.populateDefaults(context: modelContext) } .onAppear { -// Bookmark.deleteAll(context: modelContext) + // Bookmark.deleteAll(context: modelContext) } .contextMenu(forSelectionType: Bookmark.self) { items in if let item = items.first { if item.type == .temporary { Button { - let newBookmark = Bookmark(type: .server, name: item.name, address: item.address, port: item.port, login: item.login, password: item.password) + let newBookmark = Bookmark( + type: .server, name: item.name, address: item.address, port: item.port, + login: item.login, password: item.password) Bookmark.add(newBookmark, context: modelContext) } label: { Label("Bookmark", systemImage: "bookmark") } - + Divider() } - + Button { NSPasteboard.general.clearContents() NSPasteboard.general.setString(item.displayAddress, forType: .string) } label: { Label("Copy Address", systemImage: "doc.on.doc") } - + if item.type == .tracker || item.type == .server { Divider() - + if item.type == .tracker { Button { trackerSheetBookmark = item @@ -104,7 +107,7 @@ struct TrackerView: View { Label("Edit Tracker...", systemImage: "pencil") } } - + if item.type == .server { Button { bookmarkExport = BookmarkDocument(bookmark: item) @@ -113,13 +116,14 @@ struct TrackerView: View { Label("Export Bookmark...", systemImage: "bookmark.square") } } - + Divider() - + Button { Bookmark.delete(item, context: modelContext) } label: { - Label(item.type == .tracker ? "Delete Tracker" : "Delete Bookmark", systemImage: "trash") + Label( + item.type == .tracker ? "Delete Tracker" : "Delete Bookmark", systemImage: "trash") } } } @@ -127,43 +131,45 @@ struct TrackerView: View { guard let clickedItem = items.first else { return } - + if clickedItem.type == .tracker { if NSEvent.modifierFlags.contains(.option) { trackerSheetBookmark = clickedItem - } - else { + } else { clickedItem.expanded.toggle() } - } - else if let server = clickedItem.server { + } else if let server = clickedItem.server { openWindow(id: "server", value: server) } } - .fileExporter(isPresented: $bookmarkExportActive, document: bookmarkExport, contentTypes: [.data], defaultFilename: "\(bookmarkExport?.bookmark.name ?? "Hotline Bookmark").hlbm", onCompletion: { result in - switch result { - case .success(let fileURL): - print("Hotline Bookmark: Successfully exported:", fileURL) - case .failure(let err): - print("Hotline Bookmark: Failed to export:", err) - } - - bookmarkExport = nil - bookmarkExportActive = false - }, onCancellation: {}) + .fileExporter( + isPresented: $bookmarkExportActive, document: bookmarkExport, contentTypes: [.data], + defaultFilename: "\(bookmarkExport?.bookmark.name ?? "Hotline Bookmark").hlbm", + onCompletion: { result in + switch result { + case .success(let fileURL): + print("Hotline Bookmark: Successfully exported:", fileURL) + case .failure(let err): + print("Hotline Bookmark: Failed to export:", err) + } + + bookmarkExport = nil + bookmarkExportActive = false + }, onCancellation: {} + ) .onKeyPress(.rightArrow) { - if - let bookmark = selection, - bookmark.type == .tracker { + if let bookmark = selection, + bookmark.type == .tracker + { bookmark.expanded = true return .handled } return .ignored } .onKeyPress(.leftArrow) { - if - let bookmark = selection, - bookmark.type == .tracker { + if let bookmark = selection, + bookmark.type == .tracker + { bookmark.expanded = false return .handled } @@ -174,26 +180,26 @@ struct TrackerView: View { let _ = provider.loadDataRepresentation(for: UTType.fileURL) { dataRepresentation, err in // HOTLINE CREATOR CODE: 1213484099 // HOTLINE BOOKMARK TYPE CODE: 1213489773 - + if let filePathData = dataRepresentation, - let filePath = String(data: filePathData, encoding: .utf8), - let fileURL = URL(string: filePath) { - + let filePath = String(data: filePathData, encoding: .utf8), + let fileURL = URL(string: filePath) + { + print("Hotline Bookmark: Dropped from ", fileURL.path(percentEncoded: false)) - + DispatchQueue.main.async { if let newBookmark = Bookmark(fileURL: fileURL) { print("Hotline Bookmark: Added bookmark.") Bookmark.add(newBookmark, context: modelContext) - } - else { + } else { print("Hotline Bookmark: Failed to parse.") } } } } } - + return true } .sheet(item: $trackerSheetBookmark) { item in @@ -213,7 +219,7 @@ struct TrackerView: View { .frame(width: 9) .opacity(controlActiveState == .inactive ? 0.5 : 1.0) } - + ToolbarItem(placement: .primaryAction) { Button { refreshing = true @@ -225,7 +231,7 @@ struct TrackerView: View { .disabled(refreshing) .help("Refresh Trackers") } - + ToolbarItem(placement: .primaryAction) { Button { trackerSheetPresented = true @@ -234,7 +240,7 @@ struct TrackerView: View { } .help("Add Tracker") } - + ToolbarItem(placement: .primaryAction) { Button { openWindow(id: "server") @@ -250,30 +256,28 @@ struct TrackerView: View { } }) } - + func refresh() { // When a tracker is selected, refresh only that tracker. - if - let selectedBookmark = selection, - selectedBookmark.type == .tracker { + if let selectedBookmark = selection, + selectedBookmark.type == .tracker + { if !selectedBookmark.expanded { selectedBookmark.expanded = true - } - else { + } else { Task { await selectedBookmark.fetchServers() } } return } - + // Otherwise refresh/expand all trackers. for bookmark in self.bookmarks { if bookmark.type == .tracker { if !bookmark.expanded { bookmark.expanded = true - } - else { + } else { Task { await bookmark.fetchServers() } @@ -286,21 +290,21 @@ struct TrackerView: View { struct TrackerBookmarkSheet: View { @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) private var modelContext - + @State private var bookmark: Bookmark? = nil @State private var trackerAddress: String = "" @State private var trackerName: String = "" - + init() { - + } - + init(_ editingBookmark: Bookmark) { _bookmark = .init(initialValue: editingBookmark) _trackerAddress = .init(initialValue: editingBookmark.displayAddress) _trackerName = .init(initialValue: editingBookmark.name) } - + var body: some View { VStack(alignment: .leading) { Text("Type the address and name of a Hotline Tracker:") @@ -327,11 +331,11 @@ struct TrackerBookmarkSheet: View { 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 } - + if !displayName.isEmpty && !host.isEmpty { if !host.isEmpty { if self.bookmark != nil { @@ -339,16 +343,16 @@ struct TrackerBookmarkSheet: View { self.bookmark?.name = displayName self.bookmark?.address = host self.bookmark?.port = port - } - else { + } else { // We're creating a new bookmark. - let newBookmark = Bookmark(type: .tracker, name: displayName, address: host, port: port) + let newBookmark = Bookmark( + type: .tracker, name: displayName, address: host, port: port) Bookmark.add(newBookmark, context: modelContext) } - + self.trackerName = "" self.trackerAddress = "" - + dismiss() } } @@ -358,7 +362,7 @@ struct TrackerBookmarkSheet: View { Button("Cancel") { self.trackerName = "" self.trackerAddress = "" - + dismiss() } } @@ -368,9 +372,9 @@ struct TrackerBookmarkSheet: View { struct TrackerItemView: View { let bookmark: Bookmark - + @State private var onlineAnimationMaxState: Bool = true - + var body: some View { HStack(alignment: .center, spacing: 6) { if bookmark.type == .tracker { @@ -388,7 +392,7 @@ struct TrackerItemView: View { .padding(.leading, 4) .padding(.trailing, 2) } - + switch bookmark.type { case .tracker: Image("Tracker") @@ -445,11 +449,12 @@ struct TrackerItemView: View { } Spacer(minLength: 0) if let serverUserCount = bookmark.serverUserCount, - serverUserCount > 0 { + serverUserCount > 0 + { Text(String(serverUserCount)) .foregroundStyle(.secondary) .lineLimit(1) - + Circle() .fill(.fileComplete) .frame(width: 7, height: 7) @@ -468,7 +473,7 @@ struct TrackerItemView: View { guard bookmark.type == .tracker else { return } - + if bookmark.expanded { Task { await bookmark.fetchServers() @@ -479,15 +484,15 @@ struct TrackerItemView: View { } #if DEBUG -private struct TrackerViewPreview: View { - @State var selection: Bookmark? = nil + private struct TrackerViewPreview: View { + @State var selection: Bookmark? = nil - var body: some View { - TrackerView(selection: $selection) + var body: some View { + TrackerView(selection: $selection) + } } -} -#Preview { - TrackerViewPreview() -} + #Preview { + TrackerViewPreview() + } #endif |