aboutsummaryrefslogtreecommitdiff
path: root/Hotline
diff options
context:
space:
mode:
Diffstat (limited to 'Hotline')
-rw-r--r--Hotline/Assets.xcassets/File Complete.colorset/Contents.json38
-rw-r--r--Hotline/Hotline/HotlineDataBuilder.swift91
-rw-r--r--Hotline/Hotline/HotlineTransferClient.swift137
-rw-r--r--Hotline/macOS/ServerView.swift13
4 files changed, 228 insertions, 51 deletions
diff --git a/Hotline/Assets.xcassets/File Complete.colorset/Contents.json b/Hotline/Assets.xcassets/File Complete.colorset/Contents.json
new file mode 100644
index 0000000..053701f
--- /dev/null
+++ b/Hotline/Assets.xcassets/File Complete.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+ "colors" : [
+ {
+ "color" : {
+ "color-space" : "display-p3",
+ "components" : {
+ "alpha" : "1.000",
+ "blue" : "0x50",
+ "green" : "0xBC",
+ "red" : "0x5F"
+ }
+ },
+ "idiom" : "universal"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "color" : {
+ "color-space" : "srgb",
+ "components" : {
+ "alpha" : "1.000",
+ "blue" : "0x37",
+ "green" : "0x9D",
+ "red" : "0x45"
+ }
+ },
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Hotline/Hotline/HotlineDataBuilder.swift b/Hotline/Hotline/HotlineDataBuilder.swift
new file mode 100644
index 0000000..87ae966
--- /dev/null
+++ b/Hotline/Hotline/HotlineDataBuilder.swift
@@ -0,0 +1,91 @@
+import Foundation
+
+enum DataEndianness {
+ case big
+ case little
+}
+
+@resultBuilder
+struct DataBuilder {
+ static var defaultEndian: DataEndianness = .little
+
+ static func buildBlock(_ components: Data...) -> Data {
+ components.reduce(Data(), +)
+ }
+
+ static func buildExpression(_ expression: Data) -> Data {
+ expression
+ }
+
+ static func buildExpression(_ expression: String) -> Data {
+ Data(expression.utf8)
+ }
+
+ static func buildExpression(_ expression: (String, String.Encoding)) -> Data {
+ expression.0.data(using: expression.1) ?? Data()
+ }
+
+ static func buildExpression(_ expression: [UInt8]) -> Data {
+ Data(expression)
+ }
+
+ static func buildExpression(_ expression: Date) -> Data {
+ var dateData = Data()
+
+ var year: UInt16 = 0
+ var msecs: UInt16 = 0
+ var secs: UInt32 = 0
+
+ if let components = expression.hotlineDateComponents() {
+ year = components.year
+ secs = components.seconds
+ msecs = components.milliseconds
+ }
+
+ year = DataBuilder.defaultEndian == .big ? year.bigEndian : year.littleEndian
+ secs = DataBuilder.defaultEndian == .big ? secs.bigEndian : secs.littleEndian
+ msecs = DataBuilder.defaultEndian == .big ? msecs.bigEndian : msecs.littleEndian
+
+ withUnsafeBytes(of: year) { dateData.append(Data($0)) }
+ withUnsafeBytes(of: msecs) { dateData.append(Data($0)) }
+ withUnsafeBytes(of: secs) { dateData.append(Data($0)) }
+
+ return dateData
+ }
+
+ static func buildExpression(_ expression: Int) -> Data {
+ print("ADDING BYTE:", expression)
+ return withUnsafeBytes(of: UInt8(expression)) { Data($0) }
+ }
+
+ static func buildExpression<T: FixedWidthInteger>(_ expression: (T, DataEndianness)) -> Data {
+ print("ADDING INTEGER:", expression)
+ let value = expression.1 == .little ? expression.0.littleEndian : expression.0.bigEndian
+ return withUnsafeBytes(of: value) { Data($0) }
+ }
+
+ static func buildExpression<T: FixedWidthInteger>(_ expression: T) -> Data {
+ buildExpression((expression, DataBuilder.defaultEndian))
+ }
+
+ // Support for if statements
+ static func buildEither(first component: Data) -> Data {
+ component
+ }
+
+ static func buildEither(second component: Data) -> Data {
+ component
+ }
+
+ // Support for optionals
+ static func buildOptional(_ component: Data?) -> Data {
+ component ?? Data()
+ }
+}
+
+extension Data {
+ init(endian: DataEndianness = .little, @DataBuilder _ content: () -> Data) {
+ DataBuilder.defaultEndian = endian
+ self = content()
+ }
+}
diff --git a/Hotline/Hotline/HotlineTransferClient.swift b/Hotline/Hotline/HotlineTransferClient.swift
index 6c5db84..262c5ed 100644
--- a/Hotline/Hotline/HotlineTransferClient.swift
+++ b/Hotline/Hotline/HotlineTransferClient.swift
@@ -42,12 +42,6 @@ protocol HotlineFileUploadClientDelegate: HotlineTransferDelegate {
func hotlineFileUploadComplete(client: HotlineFileUploadClient, reference: UInt32)
}
-//enum HotlineFileTransferType {
-// case fileDownload
-// case filePreview
-// case fileUpload
-//}
-
enum HotlineFileTransferStage: Int {
case fileHeader = 1
case fileForkHeader = 2
@@ -257,11 +251,16 @@ class HotlineFileUploadClient: HotlineTransferClient {
print("Upload: Sending magic")
self.status = .progress(0.0)
- var magicData = Data()
- magicData.appendUInt32("HTXF".fourCharCode())
- magicData.appendUInt32(self.referenceNumber)
- magicData.appendUInt32(self.payloadSize)
- magicData.appendUInt32(0)
+ let magicData = Data(endian: .big) {
+ "HTXF".fourCharCode()
+ self.referenceNumber
+ self.payloadSize
+ UInt32.zero
+ }
+// magicData.appendUInt32("HTXF".fourCharCode())
+// magicData.appendUInt32(self.referenceNumber)
+// magicData.appendUInt32(self.payloadSize)
+// magicData.appendUInt32(0)
self.stage = .fileHeader
self.sendFileData(magicData)
@@ -505,11 +504,12 @@ class HotlineFilePreviewClient: HotlineTransferClient {
return
}
- var headerData = Data()
- headerData.appendUInt32("HTXF".fourCharCode())
- headerData.appendUInt32(self.referenceNumber)
- headerData.appendUInt32(0)
- headerData.appendUInt32(0)
+ let headerData = Data(endian: .big) {
+ "HTXF".fourCharCode()
+ self.referenceNumber
+ UInt32.zero
+ UInt32.zero
+ }
c.send(content: headerData, completion: .contentProcessed { [weak self] (error) in
guard let self = self else {
@@ -719,11 +719,21 @@ class HotlineFileDownloadClient: HotlineTransferClient {
return
}
- var headerData = Data()
- headerData.appendUInt32("HTXF".fourCharCode())
- headerData.appendUInt32(self.referenceNumber)
- headerData.appendUInt32(0)
- headerData.appendUInt32(0)
+
+ // Original method
+// var headerData = Data()
+// headerData.appendUInt32("HTXF".fourCharCode())
+// headerData.appendUInt32(self.referenceNumber)
+// headerData.appendUInt32(0)
+// headerData.appendUInt32(0)
+
+ // Result builder method
+ let headerData = Data(endian: .big) {
+ "HTXF".fourCharCode()
+ self.referenceNumber
+ UInt32.zero
+ UInt32.zero
+ }
c.send(content: headerData, completion: .contentProcessed { [weak self] (error) in
guard let self = self else {
@@ -1046,14 +1056,21 @@ struct HotlineFileHeader {
}
func data() -> Data {
- var d = Data()
-
- d.appendUInt32(self.format)
- d.appendUInt16(self.version)
- d.appendZeros(count: 16)
- d.appendUInt16(self.forkCount)
+ Data(endian: .big) {
+ self.format
+ self.version
+ Data(repeating: 0, count: 16)
+ self.forkCount
+ }
- return d
+// var d = Data()
+//
+// d.appendUInt32(self.format)
+// d.appendUInt16(self.version)
+// d.appendZeros(count: 16)
+// d.appendUInt16(self.forkCount)
+//
+// return d
}
}
@@ -1085,14 +1102,21 @@ struct HotlineFileForkHeader {
}
func data() -> Data {
- var d = Data()
-
- d.appendUInt32(self.forkType)
- d.appendUInt32(self.compressionType)
- d.appendUInt32(0)
- d.appendUInt32(self.dataSize)
+ Data(endian: .big) {
+ self.forkType
+ self.compressionType
+ UInt32.zero
+ self.dataSize
+ }
- return d
+// var d = Data()
+//
+// d.appendUInt32(self.forkType)
+// d.appendUInt32(self.compressionType)
+// d.appendUInt32(0)
+// d.appendUInt32(self.dataSize)
+//
+// return d
}
var isInfoFork: Bool {
@@ -1224,21 +1248,36 @@ struct HotlineFileInfoFork {
}
func data() -> Data {
- var d = Data()
-
- d.appendUInt32(self.platform)
- d.appendUInt32(self.type)
- d.appendUInt32(self.creator)
- d.appendUInt32(self.flags)
- d.appendUInt32(self.platformFlags)
- d.appendZeros(count: 32)
- d.appendDate(self.createdDate)
- d.appendDate(self.modifiedDate)
- d.appendUInt16(self.nameScript)
+ Data(endian: .big) {
+ self.platform
+ self.type
+ self.creator
+ self.flags
+ self.platformFlags
+ Data(repeating: 0, count: 32)
+ self.createdDate
+ self.modifiedDate
+ self.nameScript
+ UInt16(self.name.count)
+ (self.name, .macOSRoman)
+ }
- d.appendUInt16(UInt16(self.name.count))
- d.appendString(self.name, encoding: .macOSRoman)
- return d
+// var d = Data()
+//
+// d.appendUInt32(self.platform)
+// d.appendUInt32(self.type)
+// d.appendUInt32(self.creator)
+// d.appendUInt32(self.flags)
+// d.appendUInt32(self.platformFlags)
+// d.appendZeros(count: 32)
+// d.appendDate(self.createdDate)
+// d.appendDate(self.modifiedDate)
+// d.appendUInt16(self.nameScript)
+//
+// d.appendUInt16(UInt16(self.name.count))
+// d.appendString(self.name, encoding: .macOSRoman)
+//
+// return d
}
}
diff --git a/Hotline/macOS/ServerView.swift b/Hotline/macOS/ServerView.swift
index 5b5b8e3..4e24a1b 100644
--- a/Hotline/macOS/ServerView.swift
+++ b/Hotline/macOS/ServerView.swift
@@ -579,6 +579,7 @@ struct ServerView: View {
struct TransferItemView: View {
let transfer: TransferInfo
+ @Environment(\.controlActiveState) private var controlActiveState
@Environment(Hotline.self) private var model: Hotline
@State private var hovered: Bool = false
@State private var buttonHovered: Bool = false
@@ -607,6 +608,7 @@ struct TransferItemView: View {
Spacer()
FileIconView(filename: transfer.title)
.frame(width: 16, height: 16)
+ .opacity(controlActiveState == .inactive ? 0.5 : 1.0)
// .padding(.leading, 2)
Spacer()
}
@@ -631,22 +633,27 @@ struct TransferItemView: View {
.buttonStyle(.plain)
.padding(0)
.frame(width: 16, height: 16)
+ .opacity(controlActiveState == .inactive ? 0.5 : 1.0)
.help(transfer.completed || transfer.failed ? "Remove" : "Cancel Transfer")
.onHover { hovered in
self.buttonHovered = hovered
}
}
else if transfer.failed {
- Image(systemName: "exclamationmark.triangle")
+ Image(systemName: "exclamationmark.triangle.fill")
.resizable()
+ .symbolRenderingMode(.multicolor)
.aspectRatio(contentMode: .fit)
.frame(width: 16, height: 16)
+ .opacity(controlActiveState == .inactive ? 0.5 : 1.0)
}
else if transfer.completed {
Image(systemName: "checkmark.circle.fill")
.resizable()
+ .foregroundStyle(Color.fileComplete)
.aspectRatio(contentMode: .fit)
.frame(width: 16, height: 16)
+ .opacity(controlActiveState == .inactive ? 0.5 : 1.0)
}
else if transfer.progress == 0.0 {
ProgressView()
@@ -660,7 +667,9 @@ struct TransferItemView: View {
}
}
.onHover { hovered in
- self.hovered = hovered
+ withAnimation(.easeOut(duration: 0.25)) {
+ self.hovered = hovered
+ }
}
.help(formattedProgressHelp())
}