diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-05 22:27:17 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-02-05 22:27:17 +0100 |
| commit | 45829daa856b376b1ab04d415917110b71b1dec5 (patch) | |
| tree | 8e52daed6897b6f489d455736fe256cb9bd90fef /Hotline/Shared | |
| parent | 5c3ea897d062a47bc8cd6255fb8c36bad2f0733f (diff) | |
Apply formatting
Diffstat (limited to 'Hotline/Shared')
| -rw-r--r-- | Hotline/Shared/AsyncLinkPreview.swift | 16 | ||||
| -rw-r--r-- | Hotline/Shared/DataAdditions.swift | 7 | ||||
| -rw-r--r-- | Hotline/Shared/FileIconView.swift | 85 | ||||
| -rw-r--r-- | Hotline/Shared/FileImageView.swift | 62 | ||||
| -rw-r--r-- | Hotline/Shared/HotlinePanel.swift | 39 | ||||
| -rw-r--r-- | Hotline/Shared/NetSocket.swift | 155 | ||||
| -rw-r--r-- | Hotline/Shared/TextView.swift | 62 | ||||
| -rw-r--r-- | Hotline/Shared/URLAdditions.swift | 9 | ||||
| -rw-r--r-- | Hotline/Shared/VisualEffectView.swift | 13 |
9 files changed, 228 insertions, 220 deletions
diff --git a/Hotline/Shared/AsyncLinkPreview.swift b/Hotline/Shared/AsyncLinkPreview.swift index 89b186f..6f32abb 100644 --- a/Hotline/Shared/AsyncLinkPreview.swift +++ b/Hotline/Shared/AsyncLinkPreview.swift @@ -1,15 +1,17 @@ -import SwiftUI import LinkPresentation +import SwiftUI -fileprivate class CustomLinkView: LPLinkView { - override var intrinsicContentSize: CGSize { CGSize(width: 0, height: super.intrinsicContentSize.height) } +private class CustomLinkView: LPLinkView { + override var intrinsicContentSize: CGSize { + CGSize(width: 0, height: super.intrinsicContentSize.height) + } } struct AsyncLinkPreview: View { @State private var metadata: LPLinkMetadata? @State private var isLoading = true let url: URL? - + func fetchMetadata() async { guard let url else { self.isLoading = false @@ -24,7 +26,7 @@ struct AsyncLinkPreview: View { self.isLoading = false } } - + var body: some View { if isLoading { ProgressView() @@ -45,12 +47,12 @@ struct AsyncLinkPreview: View { struct LinkView: NSViewRepresentable { var metadata: LPLinkMetadata - + func makeNSView(context: Context) -> LPLinkView { let linkView = CustomLinkView(metadata: metadata) return linkView } - + func updateNSView(_ nsView: LPLinkView, context: Context) { // Nothing required } diff --git a/Hotline/Shared/DataAdditions.swift b/Hotline/Shared/DataAdditions.swift index 0e9dd96..1eb7f6f 100644 --- a/Hotline/Shared/DataAdditions.swift +++ b/Hotline/Shared/DataAdditions.swift @@ -10,9 +10,10 @@ extension Data { try? h.close() if bounceDock { #if os(macOS) - var downloadURL = URL(filePath: filePath) - downloadURL.resolveSymlinksInPath() - DistributedNotificationCenter.default().post(name: .init("com.apple.DownloadFileFinished"), object: downloadURL.path) + var downloadURL = URL(filePath: filePath) + downloadURL.resolveSymlinksInPath() + DistributedNotificationCenter.default().post( + name: .init("com.apple.DownloadFileFinished"), object: downloadURL.path) #endif } return true diff --git a/Hotline/Shared/FileIconView.swift b/Hotline/Shared/FileIconView.swift index d0949fa..d39ff1e 100644 --- a/Hotline/Shared/FileIconView.swift +++ b/Hotline/Shared/FileIconView.swift @@ -3,13 +3,13 @@ import UniformTypeIdentifiers struct FolderIconView: View { private func folderIcon() -> Image { -#if os(iOS) - return Image(systemName: "folder.fill") -#elseif os(macOS) - return Image(nsImage: NSWorkspace.shared.icon(for: UTType.folder)) -#endif + #if os(iOS) + return Image(systemName: "folder.fill") + #elseif os(macOS) + return Image(nsImage: NSWorkspace.shared.icon(for: UTType.folder)) + #endif } - + var body: some View { folderIcon() .resizable() @@ -20,52 +20,47 @@ struct FolderIconView: View { struct FileIconView: View { let filename: String let fileType: String? - + #if os(iOS) - private func fileIcon() -> Image { - let fileExtension = (self.filename as NSString).pathExtension - if let fileType = UTType(filenameExtension: fileExtension) { - if fileType.isSubtype(of: .movie) { - return Image(systemName: "play.rectangle") - } - else if fileType.isSubtype(of: .image) { - return Image(systemName: "photo") - } - else if fileType.isSubtype(of: .archive) { - return Image(systemName: "doc.zipper") - } - else if fileType.isSubtype(of: .text) { - return Image(systemName: "doc.text") - } - else { - return Image(systemName: "doc") + private func fileIcon() -> Image { + let fileExtension = (self.filename as NSString).pathExtension + if let fileType = UTType(filenameExtension: fileExtension) { + if fileType.isSubtype(of: .movie) { + return Image(systemName: "play.rectangle") + } else if fileType.isSubtype(of: .image) { + return Image(systemName: "photo") + } else if fileType.isSubtype(of: .archive) { + return Image(systemName: "doc.zipper") + } else if fileType.isSubtype(of: .text) { + return Image(systemName: "doc.text") + } else { + return Image(systemName: "doc") + } } + + return Image(systemName: "doc") } - - return Image(systemName: "doc") - } #elseif os(macOS) - private func fileIcon() -> Image { - let fileExtension = (self.filename as NSString).pathExtension - - if !fileExtension.isEmpty, - let uttype = UTType(filenameExtension: fileExtension) { - return Image(nsImage: NSWorkspace.shared.icon(for: uttype)) - } - else if let fileType = self.fileType, - let fileTypeExtension = FileManager.HFSTypeToExtension[fileType.lowercased()], - let uttype = UTType(filenameExtension: fileTypeExtension) { - return Image(nsImage: NSWorkspace.shared.icon(for: uttype)) - } - else { - return Image(nsImage: NSWorkspace.shared.icon(for: UTType.data)) + private func fileIcon() -> Image { + let fileExtension = (self.filename as NSString).pathExtension + + if !fileExtension.isEmpty, + let uttype = UTType(filenameExtension: fileExtension) + { + return Image(nsImage: NSWorkspace.shared.icon(for: uttype)) + } else if let fileType = self.fileType, + let fileTypeExtension = FileManager.HFSTypeToExtension[fileType.lowercased()], + let uttype = UTType(filenameExtension: fileTypeExtension) + { + return Image(nsImage: NSWorkspace.shared.icon(for: uttype)) + } else { + return Image(nsImage: NSWorkspace.shared.icon(for: UTType.data)) + } + + // Image(nsImage: NSWorkspace.shared.icon(for: UTType(filenameExtension: (filename as NSString).pathExtension) ?? UTType.content)) } - -// Image(nsImage: NSWorkspace.shared.icon(for: UTType(filenameExtension: (filename as NSString).pathExtension) ?? UTType.content)) - } #endif - var body: some View { fileIcon() .resizable() diff --git a/Hotline/Shared/FileImageView.swift b/Hotline/Shared/FileImageView.swift index 0cc50f1..141a71b 100644 --- a/Hotline/Shared/FileImageView.swift +++ b/Hotline/Shared/FileImageView.swift @@ -2,10 +2,10 @@ import SwiftUI struct FileImageView: NSViewRepresentable { var image: NSImage? - + let minimumSize: CGSize = CGSize(width: 350, height: 350) let presentationPaddingRatio: Double = 0.5 - + func makeNSView(context: Context) -> NSImageView { let imageView = NSImageView() imageView.imageScaling = .scaleProportionallyUpOrDown @@ -14,85 +14,89 @@ struct FileImageView: NSViewRepresentable { imageView.allowsCutCopyPaste = true imageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical) imageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) - + if let img = self.image { imageView.image = img DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.resizeWindowForImageView(imageView) } } - + return imageView } - + func updateNSView(_ nsView: NSImageView, context: Context) { nsView.image = self.image } - + // MARK: - - + func resizeWindowForImageView(_ imageView: NSImageView) { guard let window = imageView.window, let img = imageView.image else { return } - + var windowRect = window.contentLayoutRect - let windowChromeSize = CGSize(width: window.frame.width - windowRect.width, height: window.frame.height - windowRect.height) - + let windowChromeSize = CGSize( + width: window.frame.width - windowRect.width, height: window.frame.height - windowRect.height) + var windowMinSize: CGSize = windowRect.size let centerPoint = CGPoint(x: window.frame.midX, y: window.frame.midY) - + windowRect.size = img.size - + if let screen = window.screen { var paddedScreenSize = screen.frame.size paddedScreenSize.width *= self.presentationPaddingRatio paddedScreenSize.height *= self.presentationPaddingRatio - + windowMinSize = aspectFit(source: windowRect.size, bounds: self.minimumSize) - windowRect.size = aspectFit(source: windowRect.size, bounds: paddedScreenSize, minimum: windowMinSize) + windowRect.size = aspectFit( + source: windowRect.size, bounds: paddedScreenSize, minimum: windowMinSize) } - + windowRect.size.width += windowChromeSize.width windowRect.size.height += windowChromeSize.height - + windowRect.origin.x = centerPoint.x - windowRect.width / 2.0 windowRect.origin.y = centerPoint.y - windowRect.height / 2.0 - + window.setFrame(windowRect, display: true, animate: true) - -// Do these APIs even work?? -// window.aspectRatio = windowRect.size -// window.contentAspectRatio = windowRect.size + + // Do these APIs even work?? + // window.aspectRatio = windowRect.size + // window.contentAspectRatio = windowRect.size } - - func aspectFit(source sourceSize: CGSize, bounds boundingSize: CGSize, minimum minSize: CGSize? = nil) -> CGSize { + + func aspectFit( + source sourceSize: CGSize, bounds boundingSize: CGSize, minimum minSize: CGSize? = nil + ) -> CGSize { let sourceAspectRatio = sourceSize.width / sourceSize.height - + var fitSize: CGSize = sourceSize - + if fitSize.width > boundingSize.width { fitSize.width = boundingSize.width fitSize.height = fitSize.width / sourceAspectRatio } - + if fitSize.height > boundingSize.height { fitSize.height = boundingSize.height fitSize.width = fitSize.height * sourceAspectRatio } - + if let m = minSize { if fitSize.width < m.width { fitSize.width = m.width fitSize.height = fitSize.width / sourceAspectRatio } - + if fitSize.height < m.height { fitSize.height = m.height fitSize.width = fitSize.height * sourceAspectRatio } } - + return fitSize } } diff --git a/Hotline/Shared/HotlinePanel.swift b/Hotline/Shared/HotlinePanel.swift index 191e89a..6376a07 100644 --- a/Hotline/Shared/HotlinePanel.swift +++ b/Hotline/Shared/HotlinePanel.swift @@ -1,63 +1,68 @@ import Cocoa import SwiftUI -fileprivate let HOTLINE_PANEL_SIZE: CGSize = CGSizeMake(468, 114 - 10) +private let HOTLINE_PANEL_SIZE: CGSize = CGSizeMake(468, 114 - 10) class HotlinePanel: NSPanel { init(_ view: HotlinePanelView) { - super.init(contentRect: NSRect(x: 0, y: 0, width: HOTLINE_PANEL_SIZE.width, height: HOTLINE_PANEL_SIZE.height), styleMask: [.nonactivatingPanel, .titled, .closable, .utilityWindow, .fullSizeContentView], backing: .buffered, defer: false) - + super.init( + contentRect: NSRect( + x: 0, y: 0, width: HOTLINE_PANEL_SIZE.width, height: HOTLINE_PANEL_SIZE.height), + styleMask: [.nonactivatingPanel, .titled, .closable, .utilityWindow, .fullSizeContentView], + backing: .buffered, defer: false) + // Make sure that the panel is in front of almost all other windows self.isFloatingPanel = false self.level = .floating self.hidesOnDeactivate = true self.animationBehavior = .utilityWindow - + // Allow the panel to appear in a fullscreen space -// self.collectionBehavior.insert(.fullScreenAuxiliary) + // self.collectionBehavior.insert(.fullScreenAuxiliary) self.collectionBehavior.insert(.canJoinAllSpaces) self.collectionBehavior.insert(.ignoresCycle) - -// self.appearance = NSAppearance(named: .vibrantDark) + + // self.appearance = NSAppearance(named: .vibrantDark) // Don't delete panel state when it's closed. self.isReleasedWhenClosed = false - + self.standardWindowButton(.closeButton)?.isHidden = true self.standardWindowButton(.zoomButton)?.isHidden = true self.standardWindowButton(.miniaturizeButton)?.isHidden = true - + // Make it transparent, the view inside will have to set the background. // This is necessary because otherwise, we will have some space for the titlebar on top of the height of the view itself which we don't want. self.isOpaque = false self.backgroundColor = .clear - + // Since we don't show a statusbar, this allows us to drag the window by its background instead of the titlebar. self.isMovableByWindowBackground = true self.titlebarAppearsTransparent = true - + let hostingView = NSHostingView(rootView: view.edgesIgnoringSafeArea(.top)) hostingView.sizingOptions = [.preferredContentSize] - let visualEffectView = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: HOTLINE_PANEL_SIZE.width, height: HOTLINE_PANEL_SIZE.height)) + let visualEffectView = NSVisualEffectView( + frame: NSRect(x: 0, y: 0, width: HOTLINE_PANEL_SIZE.width, height: HOTLINE_PANEL_SIZE.height)) visualEffectView.material = .sidebar visualEffectView.blendingMode = .behindWindow visualEffectView.state = NSVisualEffectView.State.active visualEffectView.autoresizingMask = [.width, .height] visualEffectView.autoresizesSubviews = true visualEffectView.addSubview(hostingView) - + self.contentView = visualEffectView - + hostingView.frame = visualEffectView.bounds - + self.cascadeTopLeft(from: NSMakePoint(16, 16)) } - + override var canBecomeKey: Bool { return false } - + override var canBecomeMain: Bool { return false } diff --git a/Hotline/Shared/NetSocket.swift b/Hotline/Shared/NetSocket.swift index 263487b..59c26af 100644 --- a/Hotline/Shared/NetSocket.swift +++ b/Hotline/Shared/NetSocket.swift @@ -1,4 +1,3 @@ - // NetSocket.swift // A simple delegate based buffered read/write TCP socket. // Created by Dustin Mierau @@ -27,56 +26,57 @@ enum NetSocketStatus { final class NetSocket: NSObject, StreamDelegate { weak var delegate: NetSocketDelegate? = nil - + private var output: OutputStream? = nil private var input: InputStream? = nil - + private var outputBuffer: [UInt8] = [] private var inputBuffer: [UInt8] = [] - + private var readBuffer: [UInt8] = Array(repeating: 0, count: 4 * 1024) - + public func peek() -> [UInt8] { self.inputBuffer } public var available: Int { self.inputBuffer.count } - + private var status: NetSocketStatus = .disconnected - + @MainActor public func has(_ length: Int) -> Bool { return (self.available >= length) } - + override init() {} - + @MainActor public func connect(host: String, port: Int) { self.close() - + var outputStream: OutputStream? = nil var inputStream: InputStream? = nil - + self.status = .connecting - - Stream.getStreamsToHost(withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream) - + + Stream.getStreamsToHost( + withName: host, port: port, inputStream: &inputStream, outputStream: &outputStream) + self.input = inputStream self.output = outputStream - + inputStream?.delegate = self outputStream?.delegate = self - + inputStream?.schedule(in: .current, forMode: .default) outputStream?.schedule(in: .current, forMode: .default) - + inputStream?.open() outputStream?.open() } - + @MainActor public func close(_ err: Error? = nil) { print("NetSocket: Closed") - + let disconnected = (self.status != .disconnected) - + self.status = .disconnected - + self.input?.delegate = nil self.output?.delegate = nil self.input?.close() @@ -87,122 +87,120 @@ final class NetSocket: NSObject, StreamDelegate { self.output = nil self.inputBuffer = [] self.outputBuffer = [] - + if disconnected { self.delegate?.netsocketDisconnected(socket: self, error: err) } } - + @MainActor public func write(_ data: Data) { guard let output = self.output else { return } - + self.outputBuffer.append(contentsOf: data) - + if output.hasSpaceAvailable { self.writeBufferToStream() } } - + @MainActor public func write(_ data: [UInt8]) { guard let output = self.output else { return } - + self.outputBuffer.append(contentsOf: data) - + if output.hasSpaceAvailable { self.writeBufferToStream() } } - + @MainActor public func read(count: Int) -> [UInt8] { guard self.inputBuffer.count > 0, count > 0 else { return [] } - + let amountToRead = min(count, self.inputBuffer.count) let dataRead: [UInt8] = Array(self.inputBuffer[0..<amountToRead]) self.inputBuffer.removeFirst(amountToRead) - + return dataRead } - + @MainActor public func read(count: Int) -> Data { guard self.inputBuffer.count > 0, count > 0 else { return Data() } - + let amountToRead = min(count, self.inputBuffer.count) - + let dataRead: Data = Data(self.inputBuffer[0..<amountToRead]) self.inputBuffer.removeFirst(amountToRead) - + return dataRead } - + @MainActor public func readAll() -> [UInt8] { guard self.inputBuffer.count > 0 else { return [] } - + let dataRead: [UInt8] = Array(self.inputBuffer) self.inputBuffer = [] - + return dataRead } - + @MainActor public func readAll() -> Data { guard self.inputBuffer.count > 0 else { return Data() } - + let dataRead: Data = Data(self.inputBuffer) self.inputBuffer = [] - + return dataRead } - + @MainActor private func writeBufferToStream() { guard let output = self.output, self.outputBuffer.count > 0 else { return } - + let bytesWritten = output.write(self.outputBuffer, maxLength: self.outputBuffer.count) print("NetSocket => \(bytesWritten) bytes") if bytesWritten > 0 { self.outputBuffer.removeFirst(bytesWritten) self.delegate?.netsocketSent(socket: self, count: bytesWritten) - } - else if bytesWritten == -1 { + } else if bytesWritten == -1 { self.close(output.streamError) } } - + @MainActor private func readStreamToBuffer() { guard let input = self.input else { return } - + let bytesRead = input.read(&self.readBuffer, maxLength: 4 * 1024) print("NetSocket <= \(bytesRead) bytes") if bytesRead > 0 { self.inputBuffer.append(contentsOf: self.readBuffer[0..<bytesRead]) self.delegate?.netsocketReceived(socket: self, bytes: self.inputBuffer) - } - else if bytesRead == -1 { + } else if bytesRead == -1 { self.close(input.streamError) } } - + // MARK: - - + @MainActor func stream(_ aStream: Stream, handle eventCode: Stream.Event) { guard let input = self.input, let output = self.output else { return } - + switch eventCode { case .openCompleted: if aStream == input { @@ -226,44 +224,49 @@ final class NetSocket: NSObject, StreamDelegate { print("NetSocket: End encounterd") self.close() case .errorOccurred: - print("NetSocket: Error encounterd", input.streamError.debugDescription, output.streamError.debugDescription) + print( + "NetSocket: Error encounterd", input.streamError.debugDescription, + output.streamError.debugDescription) let err = input.streamError ?? output.streamError self.close(err) default: break } } - + // MARK: - - + private func setupStreamOptions() { if let input = self.input { - let socketData: Data = CFReadStreamCopyProperty(input as CFReadStream, CFStreamPropertyKey.socketNativeHandle) as! Data; - var socketHandle: CFSocketNativeHandle = 0; - (socketData as NSData).getBytes(&socketHandle, length: MemoryLayout.size(ofValue: socketHandle)); - - var value: Int = 0; - let size = UInt32(MemoryLayout.size(ofValue: value)); - - value = 1; + let socketData: Data = + CFReadStreamCopyProperty(input as CFReadStream, CFStreamPropertyKey.socketNativeHandle) + as! Data + var socketHandle: CFSocketNativeHandle = 0 + (socketData as NSData).getBytes( + &socketHandle, length: MemoryLayout.size(ofValue: socketHandle)) + + var value: Int = 0 + let size = UInt32(MemoryLayout.size(ofValue: value)) + + value = 1 if setsockopt(socketHandle, IPPROTO_TCP, TCP_NODELAY, &value, size) != 0 { - print("NetSocket: failed to set TCP_NODELAY"); + print("NetSocket: failed to set TCP_NODELAY") } // Enable keepalive - value = 1; + value = 1 if setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE, &value, size) != 0 { - print("NetSocket: failed to set SO_KEEPALIVE"); + print("NetSocket: failed to set SO_KEEPALIVE") } -// // Number of keepalives before close (including first keepalive packet) -// value = 5 -// if setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPCNT, &value, size) != 0 { -// print("NetSocket: failed to set TCP_KEEPCNT"); -// } -// // Idle time used when SO_KEEPALIVE is enabled. Sets how long connection must be idle before keepalive is sent. -// value = 60 -// if setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPALIVE, &value, size) != 0 { -// print("NetSocket: failed to set TCP_KEEPALIVE") -// } + // // Number of keepalives before close (including first keepalive packet) + // value = 5 + // if setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPCNT, &value, size) != 0 { + // print("NetSocket: failed to set TCP_KEEPCNT"); + // } + // // Idle time used when SO_KEEPALIVE is enabled. Sets how long connection must be idle before keepalive is sent. + // value = 60 + // if setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPALIVE, &value, size) != 0 { + // print("NetSocket: failed to set TCP_KEEPALIVE") + // } } } } diff --git a/Hotline/Shared/TextView.swift b/Hotline/Shared/TextView.swift index 47746e2..6361823 100644 --- a/Hotline/Shared/TextView.swift +++ b/Hotline/Shared/TextView.swift @@ -1,41 +1,41 @@ import SwiftUI struct BetterTextEditor: NSViewRepresentable { - + @Environment(\.lineSpacing) private var lineSpacing - + @Binding private var text: String - + private var customizations: [(NSTextView) -> Void] = [] - + init(text: Binding<String>) { self._text = text } - + func makeCoordinator() -> Coordinator { Coordinator(self) } - + func makeNSView(context: Context) -> NSScrollView { let scrollview = NSTextView.scrollablePlainDocumentContentTextView() let textview = scrollview.documentView as! NSTextView - + textview.string = self.text textview.delegate = context.coordinator - -// let p = NSMutableParagraphStyle() -// p.lineSpacing = self.lineSpacing -//// textview.defaultParagraphStyle = p -// textview.typingAttributes = [ -// .paragraphStyle: p -// ] - + + // let p = NSMutableParagraphStyle() + // p.lineSpacing = self.lineSpacing + //// textview.defaultParagraphStyle = p + // textview.typingAttributes = [ + // .paragraphStyle: p + // ] + textview.isEditable = true textview.isRichText = false textview.allowsUndo = true textview.isFieldEditor = false textview.usesAdaptiveColorMappingForDarkAppearance = true - textview.drawsBackground = false // true + textview.drawsBackground = false // true textview.usesRuler = false textview.usesFindBar = false textview.isIncrementalSearchingEnabled = false @@ -54,53 +54,53 @@ struct BetterTextEditor: NSViewRepresentable { textview.isContinuousSpellCheckingEnabled = true textview.setSelectedRange(NSMakeRange(0, 0)) self.customizations.forEach { $0(textview) } - + scrollview.scrollerStyle = .overlay - + return scrollview } - + func updateNSView(_ nsView: NSScrollView, context: Context) { let textview = nsView.documentView as! NSTextView - + if textview.string != text { textview.string = text } - + self.customizations.forEach { $0(textview) } } - + func betterEditorFont(_ font: NSFont) -> Self { self.customized { $0.font = font } } - + func betterEditorParagraphStyle(_ paragraphStyle: NSParagraphStyle) -> Self { self.customized { $0.defaultParagraphStyle = paragraphStyle } } - + func betterEditorAutomaticDashSubstitution(_ enabled: Bool) -> Self { self.customized { $0.isAutomaticDashSubstitutionEnabled = enabled } } - + func betterEditorAutomaticQuoteSubstitution(_ enabled: Bool) -> Self { self.customized { $0.isAutomaticQuoteSubstitutionEnabled = enabled } } - + func betterEditorAutomaticSpellingCorrection(_ enabled: Bool) -> Self { self.customized { $0.isAutomaticSpellingCorrectionEnabled = enabled } } - + func betterEditorTextInset(_ size: NSSize) -> Self { self.customized { $0.textContainerInset = size } } - + class Coordinator: NSObject, NSTextViewDelegate { var parent: BetterTextEditor - + init(_ parent: BetterTextEditor) { self.parent = parent } - + func textDidChange(_ notification: Notification) { guard let textview = notification.object as? NSTextView else { return @@ -110,7 +110,7 @@ struct BetterTextEditor: NSViewRepresentable { } } -private extension BetterTextEditor { +extension BetterTextEditor { private func customized(_ customization: @escaping (NSTextView) -> Void) -> Self { var copy = self copy.customizations.append(customization) diff --git a/Hotline/Shared/URLAdditions.swift b/Hotline/Shared/URLAdditions.swift index 1f25541..5e6a450 100644 --- a/Hotline/Shared/URLAdditions.swift +++ b/Hotline/Shared/URLAdditions.swift @@ -5,14 +5,15 @@ extension URL { let fileManager = FileManager.default var finalName = base var counter = 2 - + // Helper function to generate a new filename with a counter func makeFileName() -> String { let baseName = (base as NSString).deletingPathExtension let extensionName = (base as NSString).pathExtension - return extensionName.isEmpty ? "\(baseName) \(counter)" : "\(baseName) \(counter).\(extensionName)" + return extensionName.isEmpty + ? "\(baseName) \(counter)" : "\(baseName) \(counter).\(extensionName)" } - + // Check if file exists and append counter until a unique name is found var filePath = self.appending(component: finalName).path(percentEncoded: false) while fileManager.fileExists(atPath: filePath) { @@ -20,7 +21,7 @@ extension URL { filePath = self.appending(component: finalName).path(percentEncoded: false) counter += 1 } - + return filePath } } diff --git a/Hotline/Shared/VisualEffectView.swift b/Hotline/Shared/VisualEffectView.swift index e595c55..ec64111 100644 --- a/Hotline/Shared/VisualEffectView.swift +++ b/Hotline/Shared/VisualEffectView.swift @@ -1,21 +1,18 @@ import SwiftUI -struct VisualEffectView: NSViewRepresentable -{ +struct VisualEffectView: NSViewRepresentable { let material: NSVisualEffectView.Material let blendingMode: NSVisualEffectView.BlendingMode - - func makeNSView(context: Context) -> NSVisualEffectView - { + + func makeNSView(context: Context) -> NSVisualEffectView { let visualEffectView = NSVisualEffectView() visualEffectView.material = material visualEffectView.blendingMode = blendingMode visualEffectView.state = NSVisualEffectView.State.active return visualEffectView } - - func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context) - { + + func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context) { visualEffectView.material = material visualEffectView.blendingMode = blendingMode } |