From 5f07476b0c94af05b1f6d02e19e6104a09ec2161 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Wed, 29 Jun 2022 21:37:54 +1000 Subject: [PATCH 01/17] Add unsupported file view support --- .../Documents/WorkspaceCodeFileView.swift | 19 +++++++++++++----- CodeEdit/Documents/WorkspaceDocument.swift | 20 +++++++++++-------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index c131cd1190..511654be3e 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -39,12 +39,21 @@ struct WorkspaceCodeFileView: View { } } } else { - Text("No Editor") - .font(.system(size: 17)) - .foregroundColor(.secondary) - .frame(minHeight: 0) - .clipped() + Text("The file is not displayed in the editor because it is either binary or uses an unsupported text encoding") + .frame(maxWidth: .infinity, maxHeight: .infinity) + .safeAreaInset(edge: .top, spacing: 0) { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + } + } } + } else { + Text("No Editor") + .font(.system(size: 17)) + .foregroundColor(.secondary) + .frame(minHeight: 0) + .clipped() } } .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift index eb1cca78e1..f5e6e6a68c 100644 --- a/CodeEdit/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Documents/WorkspaceDocument.swift @@ -48,7 +48,9 @@ import TabBar func openTab(item: TabBarItemRepresentable) { do { updateNewlyOpenedTabs(item: item) - + if selectionState.selectedId != item.tabID { + selectionState.selectedId = item.tabID + } switch item.tabID { case .codeEditor: guard let file = item as? WorkspaceClient.FileItem else { return } @@ -58,9 +60,7 @@ import TabBar self.openExtension(item: plugin) } - if selectionState.selectedId != item.tabID { - selectionState.selectedId = item.tabID - } + } catch let err { Swift.print(err) } @@ -90,17 +90,21 @@ import TabBar } private func openFile(item: WorkspaceClient.FileItem) throws { + if !selectionState.openFileItems.contains(item) { + selectionState.openFileItems.append(item) + } let codeFile = try CodeFileDocument( for: item.url, withContentsOf: item.url, ofType: "public.source-code" ) - - if !selectionState.openFileItems.contains(item) { - selectionState.openFileItems.append(item) + + +// if !selectionState.openFileItems.contains(item) { +// selectionState.openFileItems.append(item) selectionState.openedCodeFiles[item] = codeFile - } +// } Swift.print("Opening file for item: ", item.url) } From 1e1a4cd161d2f8f0c46833036ddd7ec6d53e94ba Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Wed, 29 Jun 2022 21:42:47 +1000 Subject: [PATCH 02/17] open unsupport document unsupported document should be opened and show unsupport --- CodeEdit/Documents/WorkspaceDocument.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift index f5e6e6a68c..e00aa535a1 100644 --- a/CodeEdit/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Documents/WorkspaceDocument.swift @@ -60,7 +60,6 @@ import TabBar self.openExtension(item: plugin) } - } catch let err { Swift.print(err) } @@ -98,13 +97,7 @@ import TabBar withContentsOf: item.url, ofType: "public.source-code" ) - - -// if !selectionState.openFileItems.contains(item) { -// selectionState.openFileItems.append(item) - - selectionState.openedCodeFiles[item] = codeFile -// } + selectionState.openedCodeFiles[item] = codeFile Swift.print("Opening file for item: ", item.url) } From 61b8ec8147d4e7c5a0c2df4b48ad5d53eb63a92c Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Wed, 29 Jun 2022 22:13:04 +1000 Subject: [PATCH 03/17] fix line length --- CodeEdit/Documents/WorkspaceCodeFileView.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index 511654be3e..7def81c341 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -14,6 +14,10 @@ import AppPreferences struct WorkspaceCodeFileView: View { var windowController: NSWindowController + private let unsupportFileMessage = """ +The file is not displayed in the editor because it is either binary or uses an unsupported text encoding +""" + @ObservedObject var workspace: WorkspaceDocument @@ -39,7 +43,7 @@ struct WorkspaceCodeFileView: View { } } } else { - Text("The file is not displayed in the editor because it is either binary or uses an unsupported text encoding") + Text(unsupportFileMessage) .frame(maxWidth: .infinity, maxHeight: .infinity) .safeAreaInset(edge: .top, spacing: 0) { VStack(spacing: 0) { From 2d118541292f855f7e3f3b64a15dd93d705750ea Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Wed, 29 Jun 2022 22:17:17 +1000 Subject: [PATCH 04/17] Oops, remove empty line --- CodeEdit/Documents/WorkspaceCodeFileView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index 7def81c341..33d5947679 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -18,7 +18,6 @@ struct WorkspaceCodeFileView: View { The file is not displayed in the editor because it is either binary or uses an unsupported text encoding """ - @ObservedObject var workspace: WorkspaceDocument From 650b44b9b42e7af2b9b0eaca658794e7e6387f35 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Thu, 30 Jun 2022 00:45:51 +1000 Subject: [PATCH 05/17] support image documents --- .../Documents/WorkspaceCodeFileView.swift | 40 ++++++++++++---- CodeEdit/Documents/WorkspaceDocument.swift | 3 +- .../Modules/CodeFile/src/CodeFile.swift | 40 +++++++++++++++- .../CodeFile/src/Image/ImageFileView.swift | 46 ++++++++++--------- 4 files changed, 96 insertions(+), 33 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index 33d5947679..f7056b73a3 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -33,14 +33,12 @@ The file is not displayed in the editor because it is either binary or uses an u } return file.tabID == workspace.selectionState.selectedId }) { - if let codeFile = workspace.selectionState.openedCodeFiles[item] { - CodeFileView(codeFile: codeFile) - .safeAreaInset(edge: .top, spacing: 0) { - VStack(spacing: 0) { - BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) - Divider() - } - } + if let fileItem = workspace.selectionState.openedCodeFiles[item] { + if fileItem.typeOfFile == .image { + imageFileVIew(fileItem, for: item) + } else { + codeFileView(fileItem, for: item) + } } else { Text(unsupportFileMessage) .frame(maxWidth: .infinity, maxHeight: .infinity) @@ -62,6 +60,32 @@ The file is not displayed in the editor because it is either binary or uses an u .frame(maxWidth: .infinity, maxHeight: .infinity) } + @ViewBuilder + private func codeFileView( + _ codeFile: CodeFileDocument, + for item: WorkspaceClient.FileItem + ) -> some View { + CodeFileView(codeFile: codeFile) + .safeAreaInset(edge: .top, spacing: 0) { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + } + } + } + + @ViewBuilder + private func imageFileVIew( + _ imageFile: CodeFileDocument, + for item: WorkspaceClient.FileItem + ) -> some View { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + ImageFileView(imageFile: imageFile) + } + } + var body: some View { codeView .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift index e00aa535a1..1c49245bc9 100644 --- a/CodeEdit/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Documents/WorkspaceDocument.swift @@ -92,10 +92,11 @@ import TabBar if !selectionState.openFileItems.contains(item) { selectionState.openFileItems.append(item) } + let pathExtention = item.url.pathExtension let codeFile = try CodeFileDocument( for: item.url, withContentsOf: item.url, - ofType: "public.source-code" + ofType: pathExtention ) selectionState.openedCodeFiles[item] = codeFile Swift.print("Opening file for item: ", item.url) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index b97b04f79e..8bd2beedc9 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -8,10 +8,12 @@ import AppKit import Foundation import SwiftUI +import UniformTypeIdentifiers public enum CodeFileError: Error { case failedToDecode case failedToEncode + case fileTypeError } @objc(CodeFileDocument) @@ -19,6 +21,23 @@ public final class CodeFileDocument: NSDocument, ObservableObject { @Published var content = "" + @Published + var image: NSImage? + + public var typeOfFile: UTType? { + guard let fileType = fileType, let type = UTType(filenameExtension: fileType) else { + return nil + } + if type.conforms(to: UTType.image) { + return UTType.image + } + if type.conforms(to: UTType.text) { + return UTType.text + } + // TODO: support more type of documents + return nil + } + // MARK: - NSDocument override public class var autosavesInPlace: Bool { @@ -45,7 +64,24 @@ public final class CodeFileDocument: NSDocument, ObservableObject { } override public func read(from data: Data, ofType _: String) throws { - guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } - self.content = content + guard let typeOfFile = self.typeOfFile else { + guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.fileTypeError } + self.content = content + return + } + switch typeOfFile { + case .image: + guard let image = NSImage(data: data) else { throw CodeFileError.failedToDecode } + self.image = image + case .text: + guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } + self.content = content + // TODO: support more type of documents + default: + guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } + self.content = content + } } + + } diff --git a/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift b/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift index 8324d98e4c..0ed460d8ec 100644 --- a/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift +++ b/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift @@ -7,31 +7,33 @@ import SwiftUI -struct ImageFileView: View { - var body: some View { - Image("") - .resizable() - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - - func loadImageFromDiskWith(fileName: String) -> NSImage? { - - let documentDirectory = FileManager.SearchPathDirectory.documentDirectory - let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask - let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true) +public struct ImageFileView: View { - if let dirPath = paths.first { - let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName) - let image = NSImage(contentsOfFile: imageUrl.path) - return image + @ObservedObject + private var imageFile: CodeFileDocument - } - return nil + public init(imageFile: CodeFileDocument) { + self.imageFile = imageFile } -} -struct ImageFileView_Previews: PreviewProvider { - static var previews: some View { - ImageFileView() + public var body: some View { + GeometryReader { proxy in + if let image = imageFile.image { + if image.size.width > proxy.size.width || image.size.height > proxy.size.height { + ScrollView { + Image(nsImage: image) + .resizable() + .scaledToFit() + .frame(width: proxy.size.width) + } + .frame(maxHeight: .infinity) + } else { + Image(nsImage: image) + .frame(width: proxy.size.width, height: proxy.size.height) + } + } else { + EmptyView() + } + } } } From 64e96108cc0b4f1c2734dc8835880eebb6833836 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Thu, 30 Jun 2022 00:54:31 +1000 Subject: [PATCH 06/17] Delete empty line --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 8bd2beedc9..5dbab98394 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -82,6 +82,4 @@ public final class CodeFileDocument: NSDocument, ObservableObject { self.content = content } } - - } From 2e08efa55602ef6bb34b4bf083369e448c9c36db Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Thu, 30 Jun 2022 01:04:05 +1000 Subject: [PATCH 07/17] Remove TODO --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 5dbab98394..021afee00e 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -34,7 +34,6 @@ public final class CodeFileDocument: NSDocument, ObservableObject { if type.conforms(to: UTType.text) { return UTType.text } - // TODO: support more type of documents return nil } @@ -76,7 +75,6 @@ public final class CodeFileDocument: NSDocument, ObservableObject { case .text: guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } self.content = content - // TODO: support more type of documents default: guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } self.content = content From 1e5ecb302943504ccf84fdacb9c6c24658980f84 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Thu, 30 Jun 2022 01:16:50 +1000 Subject: [PATCH 08/17] Add Documentation --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 021afee00e..db2d13e8b6 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -24,6 +24,8 @@ public final class CodeFileDocument: NSDocument, ObservableObject { @Published var image: NSImage? + /* This is the main type of the document. For example, if the file is end with '.png', it will be an image, if the file is end with '.py', it will be a text file. If its neither image or text, this could be nil. + */ public var typeOfFile: UTType? { guard let fileType = fileType, let type = UTType(filenameExtension: fileType) else { return nil From f5ac190bbd4f8ccf6ab30882e30f3c8e66786c76 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Thu, 30 Jun 2022 08:39:33 +1000 Subject: [PATCH 09/17] Fix line limit --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index db2d13e8b6..fcbf05939b 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -24,7 +24,11 @@ public final class CodeFileDocument: NSDocument, ObservableObject { @Published var image: NSImage? - /* This is the main type of the document. For example, if the file is end with '.png', it will be an image, if the file is end with '.py', it will be a text file. If its neither image or text, this could be nil. + /* + This is the main type of the document. + For example, if the file is end with '.png', it will be an image, + if the file is end with '.py', it will be a text file. + If its neither image or text, this could be nil. */ public var typeOfFile: UTType? { guard let fileType = fileType, let type = UTType(filenameExtension: fileType) else { From 88aa2e1b0c66efc03cef237f19553a2e99746f4a Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 10 Jul 2022 12:38:57 +1000 Subject: [PATCH 10/17] Use QLPreviewView to support unsupported files --- .../Documents/WorkspaceCodeFileView.swift | 36 +++++++++-------- .../Modules/CodeFile/src/CodeFile.swift | 30 +++++++++++--- .../CodeFile/src/Other/OtherFileView.swift | 39 +++++++++++++++++++ 3 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index f7056b73a3..1889a30daf 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -11,12 +11,10 @@ import WorkspaceClient import StatusBar import Breadcrumbs import AppPreferences +import UniformTypeIdentifiers struct WorkspaceCodeFileView: View { var windowController: NSWindowController - private let unsupportFileMessage = """ -The file is not displayed in the editor because it is either binary or uses an unsupported text encoding -""" @ObservedObject var workspace: WorkspaceDocument @@ -34,20 +32,14 @@ The file is not displayed in the editor because it is either binary or uses an u return file.tabID == workspace.selectionState.selectedId }) { if let fileItem = workspace.selectionState.openedCodeFiles[item] { - if fileItem.typeOfFile == .image { - imageFileVIew(fileItem, for: item) - } else { + switch fileItem.typeOfFile { + case UTType.image: + imageFileView(fileItem, for: item) + case UTType.text: codeFileView(fileItem, for: item) + default: + otherFileView(fileItem, for: item) } - } else { - Text(unsupportFileMessage) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .safeAreaInset(edge: .top, spacing: 0) { - VStack(spacing: 0) { - BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) - Divider() - } - } } } else { Text("No Editor") @@ -75,7 +67,7 @@ The file is not displayed in the editor because it is either binary or uses an u } @ViewBuilder - private func imageFileVIew( + private func imageFileView( _ imageFile: CodeFileDocument, for item: WorkspaceClient.FileItem ) -> some View { @@ -86,6 +78,18 @@ The file is not displayed in the editor because it is either binary or uses an u } } + @ViewBuilder + private func otherFileView( + _ otherFile: CodeFileDocument, + for item: WorkspaceClient.FileItem + ) -> some View { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + OtherFileView(otherFile) + } + } + var body: some View { codeView .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index fcbf05939b..80d5eef1f6 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -9,6 +9,7 @@ import AppKit import Foundation import SwiftUI import UniformTypeIdentifiers +import QuickLookUI public enum CodeFileError: Error { case failedToDecode @@ -17,7 +18,8 @@ public enum CodeFileError: Error { } @objc(CodeFileDocument) -public final class CodeFileDocument: NSDocument, ObservableObject { +public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem { + @Published var content = "" @@ -28,21 +30,35 @@ public final class CodeFileDocument: NSDocument, ObservableObject { This is the main type of the document. For example, if the file is end with '.png', it will be an image, if the file is end with '.py', it will be a text file. + If text content is not empty, return text If its neither image or text, this could be nil. */ public var typeOfFile: UTType? { + if !self.content.isEmpty { + return UTType.text + } guard let fileType = fileType, let type = UTType(filenameExtension: fileType) else { return nil } if type.conforms(to: UTType.image) { return UTType.image } - if type.conforms(to: UTType.text) { + if type.conforms(to: UTType.text){ return UTType.text } return nil } + /* + This is the QLPreviewItemURL + */ + public var previewItemURL: URL { + guard let fileURL = self.fileURL else { + return URL(string: "")! + } + return fileURL + } + // MARK: - NSDocument override public class var autosavesInPlace: Bool { @@ -68,21 +84,23 @@ public final class CodeFileDocument: NSDocument, ObservableObject { return data } + /// This fuction is used for decoding files. + /// It should not throw error as unsupported files can still be opened by QLPreviewView. override public func read(from data: Data, ofType _: String) throws { guard let typeOfFile = self.typeOfFile else { - guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.fileTypeError } + guard let content = String(data: data, encoding: .utf8) else { return } self.content = content return } switch typeOfFile { case .image: - guard let image = NSImage(data: data) else { throw CodeFileError.failedToDecode } + guard let image = NSImage(data: data) else { return } self.image = image case .text: - guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } + guard let content = String(data: data, encoding: .utf8) else { return } self.content = content default: - guard let content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode } + guard let content = String(data: data, encoding: .utf8) else { return } self.content = content } } diff --git a/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift new file mode 100644 index 0000000000..32322f6404 --- /dev/null +++ b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift @@ -0,0 +1,39 @@ +// +// OtherFileView.swift +// +// +// Created by Shibo Tong on 10/7/2022. +// + +import SwiftUI +import QuickLookUI + +/// A SwiftUI Wrapper for `QLPreviewView` +/// Mainly used for other unsupported files +/// ## Usage +/// ```swift +/// OtherFileView(otherFile) +/// ``` +public struct OtherFileView: NSViewRepresentable { + + @ObservedObject + private var otherFile: CodeFileDocument + + /// Initialize the OtherFileView + /// - Parameter otherFile: a file which contains URL to show preview + public init( + _ otherFile: CodeFileDocument + ) { + self.otherFile = otherFile + } + + public func makeNSView(context: Context) -> QLPreviewView { + let qlPreviewView = QLPreviewView() + qlPreviewView.previewItem = otherFile + return qlPreviewView + } + + public func updateNSView(_ nsView: QLPreviewView, context: Context) { + + } +} From 32f25d946beca34fa3d543c35e6a3ec333e71939 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 10 Jul 2022 18:05:24 +1000 Subject: [PATCH 11/17] update preview item in OtherFileView --- .../Modules/CodeFile/src/Other/OtherFileView.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift index 32322f6404..8215a89cb3 100644 --- a/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift +++ b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift @@ -16,7 +16,6 @@ import QuickLookUI /// ``` public struct OtherFileView: NSViewRepresentable { - @ObservedObject private var otherFile: CodeFileDocument /// Initialize the OtherFileView @@ -29,11 +28,13 @@ public struct OtherFileView: NSViewRepresentable { public func makeNSView(context: Context) -> QLPreviewView { let qlPreviewView = QLPreviewView() - qlPreviewView.previewItem = otherFile + qlPreviewView.previewItem = otherFile.previewItemURL as QLPreviewItem return qlPreviewView } + /// Update preview file when file changed public func updateNSView(_ nsView: QLPreviewView, context: Context) { - + nsView.previewItem = otherFile.previewItemURL as QLPreviewItem } + } From 0246c858d7da610ba29774a0b716761302ea62b8 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 10 Jul 2022 18:08:58 +1000 Subject: [PATCH 12/17] Update CodeFile.swift --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 80d5eef1f6..68bbd94d16 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -43,7 +43,7 @@ public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem if type.conforms(to: UTType.image) { return UTType.image } - if type.conforms(to: UTType.text){ + if type.conforms(to: UTType.text) { return UTType.text } return nil From a79c57b3a80288edc221b897f12ce6493ff1ffd6 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 17 Jul 2022 14:12:24 +1000 Subject: [PATCH 13/17] Update CodeEditModules/Modules/CodeFile/src/CodeFile.swift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mateusz Bąk <44930823+Matejkob@users.noreply.github.com> --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 68bbd94d16..2dfd1b4ff0 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -52,11 +52,8 @@ public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem /* This is the QLPreviewItemURL */ - public var previewItemURL: URL { - guard let fileURL = self.fileURL else { - return URL(string: "")! - } - return fileURL + public var previewItemURL: URL? { + fileURL } // MARK: - NSDocument From 228d4e45e7360b6d049a5d668046e2d2229552bb Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 17 Jul 2022 14:16:15 +1000 Subject: [PATCH 14/17] Update CodeEditModules/Modules/CodeFile/src/CodeFile.swift MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mateusz Bąk <44930823+Matejkob@users.noreply.github.com> --- CodeEditModules/Modules/CodeFile/src/CodeFile.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 2dfd1b4ff0..3203f612a4 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -84,18 +84,10 @@ public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem /// This fuction is used for decoding files. /// It should not throw error as unsupported files can still be opened by QLPreviewView. override public func read(from data: Data, ofType _: String) throws { - guard let typeOfFile = self.typeOfFile else { - guard let content = String(data: data, encoding: .utf8) else { return } - self.content = content - return - } switch typeOfFile { - case .image: + case .some(.image): guard let image = NSImage(data: data) else { return } self.image = image - case .text: - guard let content = String(data: data, encoding: .utf8) else { return } - self.content = content default: guard let content = String(data: data, encoding: .utf8) else { return } self.content = content From f46ea1940055e96ed29499c7a5aad1e052cd3ebb Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Sun, 17 Jul 2022 21:08:14 +1000 Subject: [PATCH 15/17] Update open with QLPreviewView --- .../Documents/WorkspaceCodeFileView.swift | 42 +++++++++---------- .../Modules/CodeFile/src/CodeFile.swift | 13 +----- .../CodeFile/src/Image/ImageFileView.swift | 19 ++++----- .../CodeFile/src/Other/OtherFileView.swift | 9 +++- 4 files changed, 37 insertions(+), 46 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index 1889a30daf..8c18ac8744 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -32,12 +32,9 @@ struct WorkspaceCodeFileView: View { return file.tabID == workspace.selectionState.selectedId }) { if let fileItem = workspace.selectionState.openedCodeFiles[item] { - switch fileItem.typeOfFile { - case UTType.image: - imageFileView(fileItem, for: item) - case UTType.text: + if fileItem.typeOfFile == .text { codeFileView(fileItem, for: item) - default: + } else { otherFileView(fileItem, for: item) } } @@ -56,25 +53,11 @@ struct WorkspaceCodeFileView: View { private func codeFileView( _ codeFile: CodeFileDocument, for item: WorkspaceClient.FileItem - ) -> some View { - CodeFileView(codeFile: codeFile) - .safeAreaInset(edge: .top, spacing: 0) { - VStack(spacing: 0) { - BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) - Divider() - } - } - } - - @ViewBuilder - private func imageFileView( - _ imageFile: CodeFileDocument, - for item: WorkspaceClient.FileItem ) -> some View { VStack(spacing: 0) { BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) Divider() - ImageFileView(imageFile: imageFile) + CodeFileView(codeFile: codeFile) } } @@ -86,8 +69,25 @@ struct WorkspaceCodeFileView: View { VStack(spacing: 0) { BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) Divider() - OtherFileView(otherFile) + if otherFile.typeOfFile == .image { + if let url = otherFile.previewItemURL, let image = NSImage(contentsOf: url) { + GeometryReader { proxy in + if image.size.width > proxy.size.width || image.size.height > proxy.size.height { + OtherFileView(otherFile) + } else { + OtherFileView(otherFile) + .frame(width: image.size.width, height: image.size.height) + .position(x: proxy.frame(in: .local).midX, y: proxy.frame(in: .local).midY) + } + } + } else { + OtherFileView(otherFile) + } + } else { + OtherFileView(otherFile) + } } + } var body: some View { diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift index 3203f612a4..5f04b54e67 100644 --- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift +++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift @@ -23,9 +23,6 @@ public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem @Published var content = "" - @Published - var image: NSImage? - /* This is the main type of the document. For example, if the file is end with '.png', it will be an image, @@ -84,13 +81,7 @@ public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem /// This fuction is used for decoding files. /// It should not throw error as unsupported files can still be opened by QLPreviewView. override public func read(from data: Data, ofType _: String) throws { - switch typeOfFile { - case .some(.image): - guard let image = NSImage(data: data) else { return } - self.image = image - default: - guard let content = String(data: data, encoding: .utf8) else { return } - self.content = content - } + guard let content = String(data: data, encoding: .utf8) else { return } + self.content = content } } diff --git a/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift b/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift index 0ed460d8ec..e263cfaf6e 100644 --- a/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift +++ b/CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift @@ -9,24 +9,19 @@ import SwiftUI public struct ImageFileView: View { - @ObservedObject - private var imageFile: CodeFileDocument + private let image: NSImage? - public init(imageFile: CodeFileDocument) { - self.imageFile = imageFile + public init(image: NSImage?) { + self.image = image } public var body: some View { GeometryReader { proxy in - if let image = imageFile.image { + if let image = image { if image.size.width > proxy.size.width || image.size.height > proxy.size.height { - ScrollView { - Image(nsImage: image) - .resizable() - .scaledToFit() - .frame(width: proxy.size.width) - } - .frame(maxHeight: .infinity) + Image(nsImage: image) + .resizable() + .scaledToFit() } else { Image(nsImage: image) .frame(width: proxy.size.width, height: proxy.size.height) diff --git a/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift index 8215a89cb3..1a5c2a9176 100644 --- a/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift +++ b/CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift @@ -28,13 +28,18 @@ public struct OtherFileView: NSViewRepresentable { public func makeNSView(context: Context) -> QLPreviewView { let qlPreviewView = QLPreviewView() - qlPreviewView.previewItem = otherFile.previewItemURL as QLPreviewItem + if let previewItemURL = otherFile.previewItemURL { + qlPreviewView.previewItem = previewItemURL as QLPreviewItem + } return qlPreviewView } /// Update preview file when file changed public func updateNSView(_ nsView: QLPreviewView, context: Context) { - nsView.previewItem = otherFile.previewItemURL as QLPreviewItem + if let previewItemURL = otherFile.previewItemURL { + nsView.previewItem = previewItemURL as QLPreviewItem + } + } } From 3c46eef8e24b22f10af1a50c91c7b41166abb325 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Mon, 18 Jul 2022 14:34:21 +1000 Subject: [PATCH 16/17] Use SafeAreaInset for codefile and other file view --- .../Documents/WorkspaceCodeFileView.swift | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index 8c18ac8744..af026e1bf6 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -54,11 +54,13 @@ struct WorkspaceCodeFileView: View { _ codeFile: CodeFileDocument, for item: WorkspaceClient.FileItem ) -> some View { - VStack(spacing: 0) { - BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) - Divider() - CodeFileView(codeFile: codeFile) - } + CodeFileView(codeFile: codeFile) + .safeAreaInset(edge: .top, spacing: 0) { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + } + } } @ViewBuilder @@ -66,28 +68,26 @@ struct WorkspaceCodeFileView: View { _ otherFile: CodeFileDocument, for item: WorkspaceClient.FileItem ) -> some View { - VStack(spacing: 0) { - BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) - Divider() - if otherFile.typeOfFile == .image { - if let url = otherFile.previewItemURL, let image = NSImage(contentsOf: url) { - GeometryReader { proxy in - if image.size.width > proxy.size.width || image.size.height > proxy.size.height { - OtherFileView(otherFile) - } else { - OtherFileView(otherFile) - .frame(width: image.size.width, height: image.size.height) - .position(x: proxy.frame(in: .local).midX, y: proxy.frame(in: .local).midY) - } + ZStack { + if let url = otherFile.previewItemURL, let image = NSImage(contentsOf: url), otherFile.typeOfFile == .image { + GeometryReader { proxy in + if image.size.width > proxy.size.width || image.size.height > proxy.size.height { + OtherFileView(otherFile) + } else { + OtherFileView(otherFile) + .frame(width: image.size.width, height: image.size.height) + .position(x: proxy.frame(in: .local).midX, y: proxy.frame(in: .local).midY) } - } else { - OtherFileView(otherFile) } } else { OtherFileView(otherFile) } + }.safeAreaInset(edge: .top, spacing: 0) { + VStack(spacing: 0) { + BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:)) + Divider() + } } - } var body: some View { From 04f65c0033ea34949d0d10e0394f48f9062dfcb9 Mon Sep 17 00:00:00 2001 From: Shibo Tong Date: Mon, 18 Jul 2022 15:53:37 +1000 Subject: [PATCH 17/17] Fix CircleCI Line Issue --- CodeEdit/Documents/WorkspaceCodeFileView.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift index af026e1bf6..62d3b30f7a 100644 --- a/CodeEdit/Documents/WorkspaceCodeFileView.swift +++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift @@ -69,7 +69,9 @@ struct WorkspaceCodeFileView: View { for item: WorkspaceClient.FileItem ) -> some View { ZStack { - if let url = otherFile.previewItemURL, let image = NSImage(contentsOf: url), otherFile.typeOfFile == .image { + if let url = otherFile.previewItemURL, + let image = NSImage(contentsOf: url), + otherFile.typeOfFile == .image { GeometryReader { proxy in if image.size.width > proxy.size.width || image.size.height > proxy.size.height { OtherFileView(otherFile)