Skip to content

Commit 0a6b5ec

Browse files
committed
Merge Folders and Files Storage, Make Class
1 parent ea5ee7e commit 0a6b5ec

File tree

1 file changed

+45
-65
lines changed

1 file changed

+45
-65
lines changed

CodeEdit/Features/Welcome/Model/RecentProjectsStore.swift

Lines changed: 45 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,50 @@ import CoreSpotlight
1414
///
1515
/// If a UI element needs to listen to changes in this list, listen for the
1616
/// ``RecentProjectsStore/didUpdateNotification`` notification.
17-
enum RecentProjectsStore {
17+
class RecentProjectsStore {
18+
/// The default projects store, uses the `UserDefaults.standard` storage location.
19+
static let `default` = RecentProjectsStore()
20+
1821
private static let projectsdDefaultsKey = "recentProjectPaths"
19-
private static let fileDefaultsKey = "recentFilePaths"
2022
static let didUpdateNotification = Notification.Name("RecentProjectsStore.didUpdate")
2123

22-
static func recentProjectPaths() -> [String] {
23-
UserDefaults.standard.array(forKey: projectsdDefaultsKey) as? [String] ?? []
24-
}
24+
/// The storage location for recent projeects
25+
let defaults: UserDefaults
2526

26-
static func recentProjectURLs() -> [URL] {
27-
return recentProjectPaths().map { URL(filePath: $0) }
27+
/// Create a new store with a `UserDefaults` storage location.
28+
init(defaults: UserDefaults = UserDefaults.standard) {
29+
self.defaults = defaults
2830
}
2931

30-
static func recentFilePaths() -> [String] {
31-
UserDefaults.standard.array(forKey: fileDefaultsKey) as? [String] ?? []
32+
/// Gets the recent paths array from `UserDefaults`.
33+
private func recentPaths() -> [String] {
34+
defaults.array(forKey: Self.projectsdDefaultsKey) as? [String] ?? []
3235
}
3336

34-
static func recentFileURLs() -> [URL] {
35-
return recentFilePaths().map { URL(filePath: $0) }
37+
/// Gets all recent paths from `UserDefaults` as an array of `URL`s. Includes both **projects** and
38+
/// **single files**.
39+
/// To filter for either projects or single files, use ``recentProjectURLs()`` or ``recentFileURLs``, respectively.
40+
func recentURLs() -> [URL] {
41+
recentPaths().map { URL(filePath: $0) }
3642
}
3743

38-
private static func setProjectPaths(_ paths: [String]) {
39-
var paths = paths
40-
// Remove duplicates
41-
var foundPaths = Set<String>()
42-
for (idx, path) in paths.enumerated().reversed() {
43-
if foundPaths.contains(path) {
44-
paths.remove(at: idx)
45-
} else {
46-
foundPaths.insert(path)
47-
}
48-
}
44+
/// Gets the recent **Project** `URL`s from `UserDefaults`.
45+
/// To get both single files and projects, use ``recentURLs()``.
46+
func recentProjectURLs() -> [URL] {
47+
recentURLs().filter { $0.isFolder }
48+
}
4949

50-
// Limit list to to 100 items after de-duplication
51-
UserDefaults.standard.setValue(Array(paths.prefix(100)), forKey: projectsdDefaultsKey)
52-
setDocumentControllerRecents()
53-
donateSearchableItems()
54-
NotificationCenter.default.post(name: Self.didUpdateNotification, object: nil)
50+
/// Gets the recent **Single File** `URL`s from `UserDefaults`.
51+
/// To get both single files and projects, use ``recentURLs()``.
52+
func recentFileURLs() -> [URL] {
53+
recentURLs().filter { !$0.isFolder }
5554
}
56-
private static func setFilePaths(_ paths: [String]) {
55+
56+
/// Save a new paths array to defaults. Automatically limits the list to the most recent `100` items, donates
57+
/// search items to Spotlight, and notifies observers.
58+
private func setPaths(_ paths: [String]) {
5759
var paths = paths
60+
5861
// Remove duplicates
5962
var foundPaths = Set<String>()
6063
for (idx, path) in paths.enumerated().reversed() {
@@ -66,7 +69,7 @@ enum RecentProjectsStore {
6669
}
6770

6871
// Limit list to to 100 items after de-duplication
69-
UserDefaults.standard.setValue(Array(paths.prefix(100)), forKey: fileDefaultsKey )
72+
defaults.setValue(Array(paths.prefix(100)), forKey: Self.projectsdDefaultsKey)
7073
setDocumentControllerRecents()
7174
donateSearchableItems()
7275
NotificationCenter.default.post(name: Self.didUpdateNotification, object: nil)
@@ -76,66 +79,43 @@ enum RecentProjectsStore {
7679
/// Moves the path to the front if it was in the list already, or prepends it.
7780
/// Saves the list to defaults when called.
7881
/// - Parameter url: The url that was opened. Any url is accepted. File, directory, https.
79-
static func documentOpened(at url: URL) {
80-
var projPaths = recentProjectURLs()
81-
var filePaths = recentFileURLs()
82+
func documentOpened(at url: URL) {
83+
var projectURLs = recentURLs()
8284

83-
let urlToString = url.absoluteString
84-
85-
// if file portion of local URL has "/" at the end then it is a folder , files and folders go in two separate lists
86-
87-
if urlToString.hasSuffix("/") {
88-
if let containedIndex = projPaths.firstIndex(where: { $0.componentCompare(url) }) {
89-
projPaths.move(fromOffsets: IndexSet(integer: containedIndex), toOffset: 0)
90-
} else {
91-
projPaths.insert(url, at: 0)
92-
}
93-
setProjectPaths(projPaths.map { $0.path(percentEncoded: false) })
85+
if let containedIndex = projectURLs.firstIndex(where: { $0.componentCompare(url) }) {
86+
projectURLs.move(fromOffsets: IndexSet(integer: containedIndex), toOffset: 0)
9487
} else {
95-
if let containedIndex = filePaths.firstIndex(where: { $0.componentCompare(url) }) {
96-
filePaths.move(fromOffsets: IndexSet(integer: containedIndex), toOffset: 0)
97-
} else {
98-
filePaths.insert(url, at: 0)
99-
}
100-
setFilePaths(filePaths.map { $0.path(percentEncoded: false) })
88+
projectURLs.insert(url, at: 0)
10189
}
90+
91+
setPaths(projectURLs.map { $0.path(percentEncoded: false) })
10292
}
10393

10494
/// Remove all project paths in the set.
10595
/// - Parameter paths: The paths to remove.
10696
/// - Returns: The remaining urls in the recent projects list.
107-
static func removeRecentProjects(_ paths: Set<URL>) -> [URL] {
97+
func removeRecentProjects(_ paths: Set<URL>) -> [URL] {
10898
var recentProjectPaths = recentProjectURLs()
10999
recentProjectPaths.removeAll(where: { paths.contains($0) })
110-
setProjectPaths(recentProjectPaths.map { $0.path(percentEncoded: false) })
100+
setPaths(recentProjectPaths.map { $0.path(percentEncoded: false) })
111101
return recentProjectURLs()
112102
}
113-
/// Remove all folder paths in the set.
114-
/// - Parameter paths: The paths to remove.
115-
/// - Returns: The remaining urls in the recent projects list.
116-
static func removeRecentFiles(_ paths: Set<URL>) -> [URL] {
117-
var recentFilePaths = recentFileURLs()
118-
recentFilePaths.removeAll(where: { paths.contains($0) })
119-
setFilePaths(recentFilePaths.map { $0.path(percentEncoded: false) })
120-
return recentFileURLs()
121-
}
122103

123-
static func clearList() {
124-
setProjectPaths([])
125-
setFilePaths([])
104+
func clearList() {
105+
setPaths([])
126106
NotificationCenter.default.post(name: Self.didUpdateNotification, object: nil)
127107
}
128108

129109
/// Syncs AppKit's recent documents list with ours, keeping the dock menu and other lists up-to-date.
130-
private static func setDocumentControllerRecents() {
110+
private func setDocumentControllerRecents() {
131111
CodeEditDocumentController.shared.clearRecentDocuments(nil)
132112
for path in recentProjectURLs().prefix(10) {
133113
CodeEditDocumentController.shared.noteNewRecentDocumentURL(path)
134114
}
135115
}
136116

137117
/// Donates all recent URLs to Core Search, making them searchable in Spotlight
138-
private static func donateSearchableItems() {
118+
private func donateSearchableItems() {
139119
let searchableItems = recentProjectURLs().map { entity in
140120
let attributeSet = CSSearchableItemAttributeSet(contentType: .content)
141121
attributeSet.title = entity.lastPathComponent

0 commit comments

Comments
 (0)