Add upload, preview sheet
This commit is contained in:
85
CHDataManagement/Push/RemotePush.swift
Normal file
85
CHDataManagement/Push/RemotePush.swift
Normal 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
|
||||
}
|
||||
}
|
71
CHDataManagement/Push/UploadSheet.swift
Normal file
71
CHDataManagement/Push/UploadSheet.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user