@@ -10,92 +10,112 @@ import SwiftUI
1010struct RecentProjectsListView : View {
1111
1212 @State private var selection : Set < URL >
13+ @State var recentProjects : [ URL ]
1314
1415 private let openDocument : ( URL ? , @escaping ( ) -> Void ) -> Void
1516 private let dismissWindow : ( ) -> Void
1617
17- @State var recentProjects : [ URL ]
18-
1918 init ( openDocument: @escaping ( URL ? , @escaping ( ) -> Void ) -> Void , dismissWindow: @escaping ( ) -> Void ) {
2019 self . openDocument = openDocument
2120 self . dismissWindow = dismissWindow
22- let projects = NSDocumentController . shared. recentDocumentURLs
23- self . recentProjects = projects
24- self . _selection = . init( wrappedValue: Set ( Array ( projects. prefix ( 1 ) ) ) )
25- }
2621
27- var body : some View {
28- if recentProjects. isEmpty {
29- VStack {
30- Spacer ( )
31- Text ( NSLocalizedString ( " No Recent Projects " , comment: " " ) )
32- . font ( . system( size: 20 ) )
33- Spacer ( )
34- }
35- } else {
36- List ( recentProjects, id: \. self, selection: $selection) { project in
37- RecentProjectItem ( projectPath: project)
38- }
39- . listStyle ( . sidebar)
40- . contextMenu ( forSelectionType: URL . self) { items in
41- switch items. count {
42- case 0 :
43- EmptyView ( )
44- default :
45- Button ( " Show in Finder " ) {
46- NSWorkspace . shared. activateFileViewerSelecting ( Array ( items) )
47- }
22+ let recentProjectPaths : [ String ] = UserDefaults . standard. array (
23+ forKey: " recentProjectPaths "
24+ ) as? [ String ] ?? [ ]
25+ let projectsURL = recentProjectPaths. map { URL ( filePath: $0) }
26+ _selection = . init( initialValue: Set ( projectsURL. prefix ( 1 ) ) )
27+ _recentProjects = . init( initialValue: projectsURL)
28+ }
4829
49- Button ( " Copy path \( items. count > 1 ? " s " : " " ) " ) {
50- let pasteBoard = NSPasteboard . general
51- pasteBoard. clearContents ( )
52- pasteBoard. writeObjects ( selection. map ( \. relativePath) as [ NSString ] )
53- }
30+ var listEmptyView : some View {
31+ VStack {
32+ Spacer ( )
33+ Text ( NSLocalizedString ( " No Recent Projects " , comment: " " ) )
34+ . font ( . body)
35+ . foregroundColor ( . secondary)
36+ Spacer ( )
37+ }
38+ }
5439
55- Button ( " Remove from Recents " ) {
56- let oldItems = NSDocumentController . shared. recentDocumentURLs
57- NSDocumentController . shared. clearRecentDocuments ( nil )
58- oldItems. filter { !items. contains ( $0) } . reversed ( ) . forEach { url in
59- NSDocumentController . shared. noteNewRecentDocumentURL ( url)
60- }
40+ var body : some View {
41+ List ( recentProjects, id: \. self, selection: $selection) { project in
42+ RecentProjectItem ( projectPath: project)
43+ }
44+ . listStyle ( . sidebar)
45+ . contextMenu ( forSelectionType: URL . self) { items in
46+ switch items. count {
47+ case 0 :
48+ EmptyView ( )
49+ default :
50+ Button ( " Show in Finder " ) {
51+ NSWorkspace . shared. activateFileViewerSelecting ( Array ( items) )
52+ }
6153
62- recentProjects = NSDocumentController . shared. recentDocumentURLs
63- }
54+ Button ( " Copy path \( items. count > 1 ? " s " : " " ) " ) {
55+ let pasteBoard = NSPasteboard . general
56+ pasteBoard. clearContents ( )
57+ pasteBoard. writeObjects ( selection. map ( \. relativePath) as [ NSString ] )
6458 }
65- } primaryAction : { items in
66- items . forEach {
67- openDocument ( $0 , dismissWindow )
59+
60+ Button ( " Remove from Recents " ) {
61+ removeRecentProjects ( items )
6862 }
6963 }
70- . onCopyCommand {
71- selection. map {
72- NSItemProvider ( object: $0. path ( percentEncoded: false ) as NSString )
73- }
64+ } primaryAction: { items in
65+ items. forEach {
66+ openDocument ( $0, dismissWindow)
7467 }
75- . onDeleteCommand {
76- let oldItems = NSDocumentController . shared. recentDocumentURLs
77- NSDocumentController . shared. clearRecentDocuments ( nil )
78- oldItems. filter { !selection. contains ( $0) } . reversed ( ) . forEach { url in
79- NSDocumentController . shared. noteNewRecentDocumentURL ( url)
80- }
81-
82- recentProjects = NSDocumentController . shared. recentDocumentURLs
68+ }
69+ . onCopyCommand {
70+ selection. map {
71+ NSItemProvider ( object: $0. path ( percentEncoded: false ) as NSString )
8372 }
84- . background ( EffectView ( . underWindowBackground, blendingMode: . behindWindow) )
85- . onReceive ( NSApp . publisher ( for: \. keyWindow) ) { _ in
86- // Update the list whenever the key window changes.
87- // Ideally, this should be 'whenever a doc opens/closes'.
88- recentProjects = NSDocumentController . shared. recentDocumentURLs
73+ }
74+ . onDeleteCommand {
75+ removeRecentProjects ( selection)
76+ }
77+ . background ( EffectView ( . underWindowBackground, blendingMode: . behindWindow) )
78+ . onReceive ( NSApp . publisher ( for: \. keyWindow) ) { _ in
79+ // Update the list whenever the key window changes.
80+ // Ideally, this should be 'whenever a doc opens/closes'.
81+ updateRecentProjects ( )
82+ }
83+ . background {
84+ Button ( " " ) {
85+ selection. forEach {
86+ openDocument ( $0, dismissWindow)
87+ }
8988 }
90- . background {
91- Button ( " " ) {
92- selection. forEach {
93- openDocument ( $0, dismissWindow)
94- }
89+ . keyboardShortcut ( . defaultAction)
90+ . hidden ( )
91+ }
92+ . overlay {
93+ Group {
94+ if recentProjects. isEmpty {
95+ listEmptyView
9596 }
96- . keyboardShortcut ( . defaultAction)
97- . hidden ( )
9897 }
9998 }
10099 }
100+
101+ func removeRecentProjects( _ items: Set < URL > ) {
102+ var recentProjectPaths : [ String ] = UserDefaults . standard. array (
103+ forKey: " recentProjectPaths "
104+ ) as? [ String ] ?? [ ]
105+ items. forEach { url in
106+ recentProjectPaths. removeAll { url == URL ( filePath: $0) }
107+ selection. remove ( url)
108+ }
109+ UserDefaults . standard. set ( recentProjectPaths, forKey: " recentProjectPaths " )
110+ let projectsURL = recentProjectPaths. map { URL ( filePath: $0) }
111+ recentProjects = projectsURL
112+ }
113+
114+ func updateRecentProjects( ) {
115+ let recentProjectPaths : [ String ] = UserDefaults . standard. array (
116+ forKey: " recentProjectPaths "
117+ ) as? [ String ] ?? [ ]
118+ let projectsURL = recentProjectPaths. map { URL ( filePath: $0) }
119+ recentProjects = projectsURL
120+ }
101121}
0 commit comments