Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 56 additions & 14 deletions CodeEdit/Documents/WorkspaceCodeFileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import WorkspaceClient
import StatusBar
import Breadcrumbs
import AppPreferences
import UniformTypeIdentifiers

struct WorkspaceCodeFileView: View {
var windowController: NSWindowController
Expand All @@ -30,26 +31,67 @@ struct WorkspaceCodeFileView: View {
}
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()
}
}
} else {
Text("No Editor")
.font(.system(size: 17))
.foregroundColor(.secondary)
.frame(minHeight: 0)
.clipped()
if let fileItem = workspace.selectionState.openedCodeFiles[item] {
if fileItem.typeOfFile == .text {
codeFileView(fileItem, for: item)
} else {
otherFileView(fileItem, for: item)
}
}
} else {
Text("No Editor")
.font(.system(size: 17))
.foregroundColor(.secondary)
.frame(minHeight: 0)
.clipped()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}

@ViewBuilder
Comment thread
shibotong marked this conversation as resolved.
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()
}
}
Comment on lines +57 to +63

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that in the other two methods, instead of .safeAreaInset(edge:), you used only VStack. I believe this also should work correctly here. @wdg @pkasila @lilingxi01 @lukepistrol @StefKors @austincondiff, does anyone know why someone decided to use .safeAreaInset(edge:) instead of code like this:

VStack(spacing: 0) {
   BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:))
   Divider()
   CodeFileView(codeFile: codeFile)
}

I'm wondering if we can make those three views more consistent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because if I use safeAreaInset() here, images in ScrollView will have a 1 pixel space on the top.
Screen Shot 2022-07-17 at 14 09 31

I think using VStack is making more sense.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully agree with you, and I think we should use only VStack. Using safeAreaInset seems to be unneeded to me.

@austincondiff austincondiff Jul 18, 2022 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shibotong @Matejkob We need to use safeAreaInset so that we will see the blurred vibrancy effect in the toolbar when there is overflow. The above screenshot reveals a defect in the tab bar that needs its own issue and needs to be fixed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @austincondiff I have changed these views to safeAreaInset. I think its ready to merge now

}

@ViewBuilder
private func otherFileView(
_ otherFile: CodeFileDocument,
for item: WorkspaceClient.FileItem
) -> some View {
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)
}
}.safeAreaInset(edge: .top, spacing: 0) {
VStack(spacing: 0) {
BreadcrumbsView(file: item, tappedOpenFile: workspace.openTab(item:))
Divider()
}
}
}

var body: some View {
codeView
.frame(maxWidth: .infinity, maxHeight: .infinity)
Expand Down
20 changes: 9 additions & 11 deletions CodeEdit/Documents/WorkspaceDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -58,9 +60,6 @@ import TabBar
self.openExtension(item: plugin)
}

if selectionState.selectedId != item.tabID {
selectionState.selectedId = item.tabID
}
} catch let err {
Swift.print(err)
}
Expand Down Expand Up @@ -90,17 +89,16 @@ import TabBar
}

private func openFile(item: WorkspaceClient.FileItem) throws {
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
)

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)
}

Expand Down
40 changes: 38 additions & 2 deletions CodeEditModules/Modules/CodeFile/src/CodeFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,51 @@
import AppKit
import Foundation
import SwiftUI
import UniformTypeIdentifiers
import QuickLookUI

public enum CodeFileError: Error {
case failedToDecode
case failedToEncode
case fileTypeError
}

@objc(CodeFileDocument)
public final class CodeFileDocument: NSDocument, ObservableObject {
public final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem {

@Published
var content = ""

/*
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) {
return UTType.text
}
return nil
}

/*
This is the QLPreviewItemURL
*/
public var previewItemURL: URL? {
fileURL
}

// MARK: - NSDocument

override public class var autosavesInPlace: Bool {
Expand All @@ -44,8 +78,10 @@ public final class CodeFileDocument: NSDocument, ObservableObject {
return data
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If image is set instead of content, should we not return data of the image here?


/// 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 content = String(data: data, encoding: .utf8) else { throw CodeFileError.failedToDecode }
guard let content = String(data: data, encoding: .utf8) else { return }
self.content = content
}
}
41 changes: 19 additions & 22 deletions CodeEditModules/Modules/CodeFile/src/Image/ImageFileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,28 @@

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
private let image: NSImage?

}
return nil
public init(image: NSImage?) {
self.image = image
}
}

struct ImageFileView_Previews: PreviewProvider {
static var previews: some View {
ImageFileView()
public var body: some View {
GeometryReader { proxy in
if let image = image {
if image.size.width > proxy.size.width || image.size.height > proxy.size.height {
Image(nsImage: image)
.resizable()
.scaledToFit()
} else {
Image(nsImage: image)
.frame(width: proxy.size.width, height: proxy.size.height)
}
} else {
EmptyView()
}
}
}
}
45 changes: 45 additions & 0 deletions CodeEditModules/Modules/CodeFile/src/Other/OtherFileView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// 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 {

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()
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) {
if let previewItemURL = otherFile.previewItemURL {
nsView.previewItem = previewItemURL as QLPreviewItem
}

}

}