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
154 changes: 87 additions & 67 deletions CodeEdit/Features/Welcome/Views/RecentProjectsListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,92 +10,112 @@ import SwiftUI
struct RecentProjectsListView: View {

@State private var selection: Set<URL>
@State var recentProjects: [URL]

private let openDocument: (URL?, @escaping () -> Void) -> Void
private let dismissWindow: () -> Void

@State var recentProjects: [URL]

init(openDocument: @escaping (URL?, @escaping () -> Void) -> Void, dismissWindow: @escaping () -> Void) {
self.openDocument = openDocument
self.dismissWindow = dismissWindow
let projects = NSDocumentController.shared.recentDocumentURLs
self.recentProjects = projects
self._selection = .init(wrappedValue: Set(Array(projects.prefix(1))))
}

var body: some View {
if recentProjects.isEmpty {
VStack {
Spacer()
Text(NSLocalizedString("No Recent Projects", comment: ""))
.font(.system(size: 20))
Spacer()
}
} else {
List(recentProjects, id: \.self, selection: $selection) { project in
RecentProjectItem(projectPath: project)
}
.listStyle(.sidebar)
.contextMenu(forSelectionType: URL.self) { items in
switch items.count {
case 0:
EmptyView()
default:
Button("Show in Finder") {
NSWorkspace.shared.activateFileViewerSelecting(Array(items))
}
let recentProjectPaths: [String] = UserDefaults.standard.array(
forKey: "recentProjectPaths"
) as? [String] ?? []
let projectsURL = recentProjectPaths.map { URL(filePath: $0) }
_selection = .init(initialValue: Set(projectsURL.prefix(1)))
_recentProjects = .init(initialValue: projectsURL)
}

Button("Copy path\(items.count > 1 ? "s" : "")") {
let pasteBoard = NSPasteboard.general
pasteBoard.clearContents()
pasteBoard.writeObjects(selection.map(\.relativePath) as [NSString])
}
var listEmptyView: some View {
VStack {
Spacer()
Text(NSLocalizedString("No Recent Projects", comment: ""))
.font(.body)
.foregroundColor(.secondary)
Spacer()
}
}

Button("Remove from Recents") {
let oldItems = NSDocumentController.shared.recentDocumentURLs
NSDocumentController.shared.clearRecentDocuments(nil)
oldItems.filter { !items.contains($0) }.reversed().forEach { url in
NSDocumentController.shared.noteNewRecentDocumentURL(url)
}
var body: some View {
List(recentProjects, id: \.self, selection: $selection) { project in
RecentProjectItem(projectPath: project)
}
.listStyle(.sidebar)
.contextMenu(forSelectionType: URL.self) { items in
switch items.count {
case 0:
EmptyView()
default:
Button("Show in Finder") {
NSWorkspace.shared.activateFileViewerSelecting(Array(items))
}

recentProjects = NSDocumentController.shared.recentDocumentURLs
}
Button("Copy path\(items.count > 1 ? "s" : "")") {
let pasteBoard = NSPasteboard.general
pasteBoard.clearContents()
pasteBoard.writeObjects(selection.map(\.relativePath) as [NSString])
}
} primaryAction: { items in
items.forEach {
openDocument($0, dismissWindow)

Button("Remove from Recents") {
removeRecentProjects(items)
}
}
.onCopyCommand {
selection.map {
NSItemProvider(object: $0.path(percentEncoded: false) as NSString)
}
} primaryAction: { items in
items.forEach {
openDocument($0, dismissWindow)
}
.onDeleteCommand {
let oldItems = NSDocumentController.shared.recentDocumentURLs
NSDocumentController.shared.clearRecentDocuments(nil)
oldItems.filter { !selection.contains($0) }.reversed().forEach { url in
NSDocumentController.shared.noteNewRecentDocumentURL(url)
}

recentProjects = NSDocumentController.shared.recentDocumentURLs
}
.onCopyCommand {
selection.map {
NSItemProvider(object: $0.path(percentEncoded: false) as NSString)
}
.background(EffectView(.underWindowBackground, blendingMode: .behindWindow))
.onReceive(NSApp.publisher(for: \.keyWindow)) { _ in
// Update the list whenever the key window changes.
// Ideally, this should be 'whenever a doc opens/closes'.
recentProjects = NSDocumentController.shared.recentDocumentURLs
}
.onDeleteCommand {
removeRecentProjects(selection)
}
.background(EffectView(.underWindowBackground, blendingMode: .behindWindow))
.onReceive(NSApp.publisher(for: \.keyWindow)) { _ in
// Update the list whenever the key window changes.
// Ideally, this should be 'whenever a doc opens/closes'.
updateRecentProjects()
}
.background {
Button("") {
selection.forEach {
openDocument($0, dismissWindow)
}
}
.background {
Button("") {
selection.forEach {
openDocument($0, dismissWindow)
}
.keyboardShortcut(.defaultAction)
.hidden()
}
.overlay {
Group {
if recentProjects.isEmpty {
listEmptyView
}
.keyboardShortcut(.defaultAction)
.hidden()
}
}
}

func removeRecentProjects(_ items: Set<URL>) {
var recentProjectPaths: [String] = UserDefaults.standard.array(
forKey: "recentProjectPaths"
) as? [String] ?? []
items.forEach { url in
recentProjectPaths.removeAll { url == URL(filePath: $0) }
selection.remove(url)
}
UserDefaults.standard.set(recentProjectPaths, forKey: "recentProjectPaths")
let projectsURL = recentProjectPaths.map { URL(filePath: $0) }
recentProjects = projectsURL
}

func updateRecentProjects() {
let recentProjectPaths: [String] = UserDefaults.standard.array(
forKey: "recentProjectPaths"
) as? [String] ?? []
let projectsURL = recentProjectPaths.map { URL(filePath: $0) }
recentProjects = projectsURL
}
}
2 changes: 1 addition & 1 deletion CodeEdit/Features/Welcome/Views/WelcomeWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct WelcomeWindow: Scene {
dismiss()
CodeEditDocumentController.shared.openDocument(
onCompletion: { _, _ in opened() },
onCancel: { openWindow(id: "Welcome") }
onCancel: { openWindow(id: SceneID.welcome.rawValue) }
)
}
} newDocument: {
Expand Down