aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Hotline/Hotline/HotlineClient.swift9
-rw-r--r--Hotline/Models/Hotline.swift72
-rw-r--r--Hotline/macOS/FilesView.swift115
-rw-r--r--Hotline/macOS/NewsView.swift15
4 files changed, 133 insertions, 78 deletions
diff --git a/Hotline/Hotline/HotlineClient.swift b/Hotline/Hotline/HotlineClient.swift
index 1c72ab0..b30ee11 100644
--- a/Hotline/Hotline/HotlineClient.swift
+++ b/Hotline/Hotline/HotlineClient.swift
@@ -628,6 +628,15 @@ class HotlineClient: NetSocketDelegate {
}
}
+ @MainActor func sendDeleteFile(name fileName: String, path filePath: [String], callback: ((Bool) -> Void)? = nil) {
+ var t = HotlineTransaction(type: .deleteFile)
+ t.setFieldString(type: .fileName, val: fileName)
+ t.setFieldPath(type: .filePath, val: filePath)
+ self.sendPacket(t) { reply, err in
+ callback?(err == nil)
+ }
+ }
+
@MainActor func sendGetFileInfo(name fileName: String, path filePath: [String], callback: ((FileDetails?) -> Void)? = nil) {
var t = HotlineTransaction(type: .getFileInfo)
t.setFieldString(type: .fileName, val: fileName)
diff --git a/Hotline/Models/Hotline.swift b/Hotline/Models/Hotline.swift
index 06baf04..ce917cd 100644
--- a/Hotline/Models/Hotline.swift
+++ b/Hotline/Models/Hotline.swift
@@ -545,14 +545,29 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileClientDelegate {
}
}
- @MainActor func fileDetails(_ fileName: String, path: [String], complete callback: ((FileDetails?) -> Void)? = nil) {
+ @MainActor func getFileDetails(_ fileName: String, path: [String]) async -> FileDetails? {
var fullPath: [String] = []
if path.count > 1 {
fullPath = Array(path[0..<path.count-1])
}
- self.client.sendGetFileInfo(name: fileName, path: fullPath) { info in
- callback?(info)
+ return await withCheckedContinuation { [weak self] continuation in
+ self?.client.sendGetFileInfo(name: fileName, path: fullPath) { info in
+ continuation.resume(returning: info)
+ }
+ }
+ }
+
+ @MainActor func deleteFile(_ fileName: String, path: [String]) async -> Bool {
+ var fullPath: [String] = []
+ if path.count > 1 {
+ fullPath = Array(path[0..<path.count-1])
+ }
+
+ return await withCheckedContinuation { [weak self] continuation in
+ self?.client.sendDeleteFile(name: fileName, path: fullPath) { success in
+ continuation.resume(returning: success)
+ }
}
}
@@ -611,57 +626,6 @@ class Hotline: Equatable, HotlineClientDelegate, HotlineFileClientDelegate {
}
}
-// @MainActor func previewFile(_ fileName: String, path: [String], addTransfer: Bool = false, complete callback: ((TransferInfo, Data) -> Void)? = nil) {
-// var fullPath: [String] = []
-// if path.count > 1 {
-// fullPath = Array(path[0..<path.count-1])
-// }
-//
-// self.client.sendDownloadFile(name: fileName, path: fullPath, preview: true, sent: { _ in
-//
-// }, reply: { [weak self] success, downloadReferenceNumber, downloadTransferSize, downloadFileSize, downloadWaitingCount in
-// guard success else {
-// return
-// }
-//
-// print("GOT DOWNLOAD REPLY:")
-// print("SUCCESS?", success)
-// print("TRANSFER SIZE: \(downloadTransferSize.debugDescription)")
-// print("FILE SIZE: \(downloadFileSize.debugDescription)")
-// print("REFERENCE NUM: \(downloadReferenceNumber.debugDescription)")
-// print("WAITING COUNT: \(downloadWaitingCount.debugDescription)")
-//
-// if
-// let self = self,
-// let address = self.server?.address,
-// let port = self.server?.port,
-// let referenceNumber = downloadReferenceNumber,
-// let transferSize = downloadTransferSize {
-//
-// let fileClient = HotlineFileClient(address: address, port: UInt16(port), reference: referenceNumber, size: UInt32(transferSize), type: .preview)
-// fileClient.delegate = self
-// self.downloads.append(fileClient)
-//
-// if addTransfer {
-// let transfer = TransferInfo(id: referenceNumber, title: fileName, size: UInt(transferSize))
-// transfer.previewCallback = callback
-// self.transfers.append(transfer)
-// }
-//
-// fileClient.downloadToMemory()
-//
-// print("DOWNLOADING TO MEMORY")
-//// fileClient.downloadToMemory({ [weak self] fileData in
-//// print("DOWNLOADED PREVIEW DATA", fileData?.count)
-//// self?.downloads.removeAll { $0.referenceNumber == referenceNumber }
-//// callback?(fileData != nil, fileData)
-//// })
-//
-//// self.downloads.append(fileClient)
-// }
-// })
-// }
-
@MainActor func deleteTransfer(id: UInt32) {
if let b = self.bannerClient, b.referenceNumber == id {
b.cancel()
diff --git a/Hotline/macOS/FilesView.swift b/Hotline/macOS/FilesView.swift
index a225549..77db291 100644
--- a/Hotline/macOS/FilesView.swift
+++ b/Hotline/macOS/FilesView.swift
@@ -127,12 +127,51 @@ struct FilesView: View {
// let _ = FilePreviewWindowController(info: previewInfo)
}
+ @MainActor private func getFileInfo(_ file: FileInfo) {
+ Task {
+ if let fileInfo = await model.getFileDetails(file.name, path: file.path) {
+ Task { @MainActor in
+ self.fileDetails = fileInfo
+ }
+ }
+ }
+ }
+
+ @MainActor private func downloadFile(_ file: FileInfo) {
+ guard !file.isFolder else {
+ return
+ }
+
+ model.downloadFile(file.name, path: file.path)
+ }
+
+ @MainActor private func previewFile(_ file: FileInfo) {
+ guard file.isPreviewable else {
+ return
+ }
+
+ model.previewFile(file.name, path: file.path) { info in
+ if let info = info {
+ openPreviewWindow(info)
+ }
+ }
+ }
+
+ private func deleteFile(_ file: FileInfo) async {
+ var parentPath: [String] = []
+ if file.path.count > 1 {
+ parentPath = Array(file.path[0..<file.path.count-1])
+ }
+
+ if await model.deleteFile(file.name, path: file.path) {
+ let _ = await model.getFileList(path: parentPath)
+ }
+ }
+
var body: some View {
NavigationStack {
List(model.files, id: \.self, selection: $selection) { file in
FileView(file: file, depth: 0).tag(file.id)
-// .environment(self.fileSelection)
-// .frame(height: 34)
}
.environment(\.defaultMinListRowHeight, 34)
.listStyle(.inset)
@@ -143,7 +182,51 @@ struct FilesView: View {
}
}
.contextMenu(forSelectionType: FileInfo.self) { items in
- // ...
+ let selectedFile = items.first
+
+ Button {
+ if let s = selectedFile, !s.isFolder {
+ downloadFile(s)
+ }
+ } label: {
+ Label("Download", systemImage: "arrow.down")
+ }
+ .disabled(selectedFile == nil || (selectedFile != nil && selectedFile!.isFolder))
+
+ Divider()
+
+ Button {
+ if let s = selectedFile {
+ getFileInfo(s)
+ }
+ } label: {
+ Label("Get Info", systemImage: "info.circle")
+ }
+ .disabled(selectedFile == nil)
+
+ Button {
+ if let s = selectedFile {
+ previewFile(s)
+ }
+ } label: {
+ Label("Preview", systemImage: "eye")
+ }
+ .disabled(selectedFile == nil || (selectedFile != nil && !selectedFile!.isPreviewable))
+
+ if model.access?.contains(.canDeleteFiles) == true {
+ Divider()
+
+ Button {
+ if let s = selectedFile {
+ Task {
+ await deleteFile(s)
+ }
+ }
+ } label: {
+ Label("Delete", systemImage: "trash")
+ }
+ .disabled(selectedFile == nil)
+ }
} primaryAction: { items in
guard let clickedFile = items.first else {
return
@@ -154,7 +237,7 @@ struct FilesView: View {
clickedFile.expanded.toggle()
}
else {
- model.downloadFile(clickedFile.name, path: clickedFile.path)
+ downloadFile(clickedFile)
}
}
.onKeyPress(.rightArrow) {
@@ -173,11 +256,7 @@ struct FilesView: View {
}
.onKeyPress(.space) {
if let s = selection, s.isPreviewable {
- model.previewFile(s.name, path: s.path) { info in
- if let info = info {
- openPreviewWindow(info)
- }
- }
+ previewFile(s)
return .handled
}
return .ignored
@@ -203,12 +282,8 @@ struct FilesView: View {
ToolbarItem(placement: .primaryAction) {
Button {
- if let s = selection, s.isPreviewable {
- model.previewFile(s.name, path: s.path) { info in
- if let info = info {
- openPreviewWindow(info)
- }
- }
+ if let selectedFile = selection, selectedFile.isPreviewable {
+ previewFile(selectedFile)
}
} label: {
Label("Preview", systemImage: "eye")
@@ -219,10 +294,8 @@ struct FilesView: View {
ToolbarItem(placement: .primaryAction) {
Button {
- if let s = selection {
- model.fileDetails(s.name, path: s.path) { info in
- fileDetails = info
- }
+ if let selectedFile = selection {
+ getFileInfo(selectedFile)
}
} label: {
Label("Get Info", systemImage: "info.circle")
@@ -233,8 +306,8 @@ struct FilesView: View {
ToolbarItem(placement: .primaryAction) {
Button {
- if let s = selection, !s.isFolder {
- model.downloadFile(s.name, path: s.path)
+ if let selectedFile = selection, !selectedFile.isFolder {
+ downloadFile(selectedFile)
}
} label: {
Label("Download", systemImage: "arrow.down")
diff --git a/Hotline/macOS/NewsView.swift b/Hotline/macOS/NewsView.swift
index ed5d969..6f24193 100644
--- a/Hotline/macOS/NewsView.swift
+++ b/Hotline/macOS/NewsView.swift
@@ -121,16 +121,15 @@ struct NewsView: View {
ToolbarItem(placement: .primaryAction) {
Button {
+ loading = true
if let selectionPath = selection?.path {
Task {
- loading = true
await model.getNewsList(at: selectionPath)
loading = false
}
}
else {
Task {
- loading = true
await model.getNewsList()
loading = false
}
@@ -153,7 +152,17 @@ struct NewsView: View {
.listStyle(.inset)
.alternatingRowBackgrounds(.enabled)
.contextMenu(forSelectionType: NewsInfo.self) { items in
- // ...
+ let selectedItem = items.first
+
+ Button {
+ if selectedItem?.type == .article {
+ replyOpen = true
+ }
+ } label: {
+ Label("Reply to \(selectedItem?.articleUsername ?? "Post")", systemImage: "arrowshape.turn.up.left")
+ }
+ .disabled(selectedItem == nil || selectedItem?.type != .article)
+
} primaryAction: { items in
guard let clickedNews = items.first else {
return