Add upload, preview sheet

This commit is contained in:
Christoph Hagen
2025-02-15 01:02:25 +01:00
parent 0753d91f29
commit 2cad27b504
14 changed files with 358 additions and 115 deletions

View File

@ -0,0 +1,85 @@
import Foundation
final class RemotePush: ObservableObject {
@Published
var isTransmittingToRemote = false
@Published
var lastPushWasSuccessful = true
func transmitToRemote(settings: GeneralSettings, outputFolder: String, outputHandler: @escaping (String) -> Void) {
guard !isTransmittingToRemote else { return }
DispatchQueue.main.async {
self.isTransmittingToRemote = true
}
DispatchQueue.global().async {
let success = self.transmit(
outputFolder: outputFolder,
remoteUser: settings.remoteUserForUpload,
remotePort: settings.remotePortForUpload,
remoteDomain: settings.url,
remotePath: settings.remotePathForUpload,
excludedItems: [".git"],
outputHandler: outputHandler)
DispatchQueue.main.async {
self.isTransmittingToRemote = false
self.lastPushWasSuccessful = success
}
}
}
private func transmit(
outputFolder: String,
remoteUser: String,
remotePort: Int,
remoteDomain: String,
remotePath: String,
excludedItems: [String],
outputHandler: @escaping (String) -> Void
) -> Bool {
let remoteDomain = remoteDomain.withHttpPrefixRemoved
let remotePath = remotePath.withLeadingSlash.withTrailingSlash
let outputFolder = outputFolder.withLeadingSlash.withTrailingSlash
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/bash")
let arguments = [
"/opt/homebrew/bin/rsync",
"-hrutv",
"--info=progress2"]
+ excludedItems.reduce(into: []) { $0 += ["--exclude", $1] }
+ [
"-e", "\"/opt/homebrew/bin/ssh -p \(remotePort)\"",
outputFolder,
"\(remoteUser)@\(remoteDomain):\(remotePath)"
]
let argument = arguments.joined(separator: " ")
process.arguments = ["-c", argument]
print(argument)
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = pipe
let fileHandle = pipe.fileHandleForReading
// Use a DispatchQueue to read output asynchronously
fileHandle.readabilityHandler = { fileHandle in
if let output = String(data: fileHandle.availableData, encoding: .utf8), !output.isEmpty {
outputHandler(output)
}
}
process.launch()
process.waitUntilExit()
if process.terminationStatus == 0 {
return true
}
return false
}
}

View File

@ -0,0 +1,71 @@
import SwiftUI
import SFSafeSymbols
struct UploadSheet: View {
@EnvironmentObject
private var content: Content
@EnvironmentObject
private var upload: RemotePush
@Environment(\.dismiss)
private var dismiss
@State
private var output = ""
private var uploadSymbol: SFSymbol {
if upload.isTransmittingToRemote {
return .squareAndArrowUpBadgeClock
}
if !upload.lastPushWasSuccessful {
return .squareAndArrowUpTrianglebadgeExclamationmark
}
return .squareAndArrowUp
}
var header: String {
let user = content.settings.general.remoteUserForUpload
let port = content.settings.general.remotePortForUpload
let url = content.settings.general.remotePathForUpload.withHttpPrefixRemoved
let path = content.settings.general.remotePathForUpload
return "\(user)@\(url):\(port)/\(path)"
}
var body: some View {
VStack {
HStack {
Button("Upload", action: startUpload)
.disabled(upload.isTransmittingToRemote)
Text(header)
Spacer()
Button("Close", action: { dismiss() })
}
ScrollView {
Text(output)
.font(.body.monospaced())
.foregroundStyle(.primary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding()
.frame(minWidth: 500, idealWidth: 600, idealHeight: 500)
}
private func startUpload() {
guard let folder = content.storage.outputScope?.url.path() else {
print("No output folder to start upload")
return
}
output = ""
upload.transmitToRemote(
settings: content.settings.general,
outputFolder: folder) { newContent in
DispatchQueue.main.async {
self.output += newContent
}
}
}
}