aboutsummaryrefslogtreecommitdiff
path: root/Hotline/macOS/TrackerView.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Hotline/macOS/TrackerView.swift')
-rw-r--r--Hotline/macOS/TrackerView.swift181
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