summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-07-05 06:36:16 -0700
committerFuwn <[email protected]>2025-07-05 06:36:16 -0700
commitfcf9ea89cf9190d4deb1e8e7223bf32a1f03b44f (patch)
treecaf89e739b6ce730eb2ff0f0ef060c00cb4f15e9
parentfeat: Development commit (diff)
downloadsora-testing-fcf9ea89cf9190d4deb1e8e7223bf32a1f03b44f.tar.xz
sora-testing-fcf9ea89cf9190d4deb1e8e7223bf32a1f03b44f.zip
feat: Development commit
-rw-r--r--Sora/Data/CollectionPickerOption.swift40
-rw-r--r--Sora/Data/Settings/SettingsFolder.swift8
-rw-r--r--Sora/Extensions/Array+RemovingDuplicates.swift9
-rw-r--r--Sora/Views/Generic/GenericListView.swift91
4 files changed, 129 insertions, 19 deletions
diff --git a/Sora/Data/CollectionPickerOption.swift b/Sora/Data/CollectionPickerOption.swift
new file mode 100644
index 0000000..442ebdc
--- /dev/null
+++ b/Sora/Data/CollectionPickerOption.swift
@@ -0,0 +1,40 @@
+import Foundation
+
+enum CollectionPickerOption: Identifiable, Hashable {
+ case all
+ case folder(UUID)
+ case topLevel(String)
+ case uncategorized
+
+ var id: String {
+ switch self {
+ case .all:
+ return "all"
+
+ case .folder(let id):
+ return id.uuidString
+
+ case .topLevel(let name):
+ return name
+
+ case .uncategorized:
+ return "uncategorized"
+ }
+ }
+
+ var name: (_ settings: SettingsManager) -> String {
+ switch self {
+ case .all:
+ return { _ in "All" }
+
+ case .folder(let id):
+ return { settings in settings.folderName(forID: id) ?? "Unknown Folder" }
+
+ case .topLevel(let name):
+ return { _ in name }
+
+ case .uncategorized:
+ return { _ in "Uncategorised" }
+ }
+ }
+}
diff --git a/Sora/Data/Settings/SettingsFolder.swift b/Sora/Data/Settings/SettingsFolder.swift
index 84543c1..2464770 100644
--- a/Sora/Data/Settings/SettingsFolder.swift
+++ b/Sora/Data/Settings/SettingsFolder.swift
@@ -5,6 +5,14 @@ struct SettingsFolder: Codable, Identifiable, Hashable {
var name: String
let createdAt: Date
+ var topLevelName: String? {
+ if name.contains("|") {
+ return String(name.split(separator: "|")[0]).trimmingCharacters(in: .whitespacesAndNewlines)
+ }
+
+ return nil
+ }
+
init(name: String, id: UUID = UUID()) {
createdAt = Date()
self.id = id
diff --git a/Sora/Extensions/Array+RemovingDuplicates.swift b/Sora/Extensions/Array+RemovingDuplicates.swift
new file mode 100644
index 0000000..15fc697
--- /dev/null
+++ b/Sora/Extensions/Array+RemovingDuplicates.swift
@@ -0,0 +1,9 @@
+import Foundation
+
+extension Array where Element: Hashable {
+ func removingDuplicates() -> [Element] {
+ var seen = Set<Element>()
+
+ return filter { seen.insert($0).inserted }
+ }
+}
diff --git a/Sora/Views/Generic/GenericListView.swift b/Sora/Views/Generic/GenericListView.swift
index b0ee422..0c8da79 100644
--- a/Sora/Views/Generic/GenericListView.swift
+++ b/Sora/Views/Generic/GenericListView.swift
@@ -1,6 +1,9 @@
+// swiftlint:disable file_length
+
import SwiftUI
-struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swiftlint:disable:this type_body_length
+// swiftlint:disable:next type_body_length
+struct GenericListView<T: Identifiable & Hashable & GenericItem>: View {
@EnvironmentObject private var settings: SettingsManager
@EnvironmentObject private var manager: BooruManager
@Binding var selectedTab: Int
@@ -11,7 +14,7 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swi
@State private var newCollectionName = ""
@State private var itemPendingCollectionAssignment: UUID?
@State private var isCollectionErrorAlertPresented = false
- @State private var selectedFolder: UUID?
+ @State private var selectedCollectionOption: CollectionPickerOption = .all
@State private var sort: SettingsBookmarkSort = .dateAdded
@State private var isCollectionPickerPresented = false
@State private var isProviderPickerPresented = false
@@ -31,15 +34,25 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swi
var filteredItems: [T] {
items.filter { item in
let matchesFolder: Bool = {
- if selectedFolder == nil {
+ switch selectedCollectionOption {
+ case .all:
return true
- }
- if selectedFolder == UUID.nilUUID() {
+ case .uncategorized:
return item.folder == nil
- }
- return item.folder == selectedFolder
+ case .topLevel(let topLevelName):
+ if let folderId = item.folder,
+ let folder = settings.folders.first(where: { $0.id == folderId }),
+ let itemTopLevelName = folder.topLevelName
+ {
+ return itemTopLevelName == topLevelName
+ }
+ return false
+
+ case .folder(let folderId):
+ return item.folder == folderId
+ }
}()
let matchesSearch =
searchText.isEmpty
@@ -76,7 +89,7 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swi
@ViewBuilder private var listContent: some View {
List {
- if filteredItems.isEmpty && (!searchText.isEmpty || !(selectedFolder == nil)) {
+ if filteredItems.isEmpty && (!searchText.isEmpty || !(selectedCollectionOption == .all)) {
Text("No matching items found")
.foregroundColor(.secondary)
}
@@ -116,16 +129,37 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swi
.padding()
.pickerStyle(.menu)
- Picker("Collection", selection: $selectedFolder) {
- Text("All").tag(nil as UUID?)
+ Picker("Collection", selection: $selectedCollectionOption) {
+ Text(CollectionPickerOption.all.name(settings)).tag(CollectionPickerOption.all)
if items.contains(where: { $0.folder == nil }) {
- Text("Uncategorised").tag(UUID.nilUUID() as UUID?)
+ Text(CollectionPickerOption.uncategorized.name(settings)).tag(
+ CollectionPickerOption.uncategorized
+ )
+ }
+
+ ForEach(
+ settings.folders
+ .filter { $0.topLevelName != nil }
+ .map { $0.topLevelName! }
+ .removingDuplicates(), id: \.self
+ ) { topLevelName in
+ Text(CollectionPickerOption.topLevel(topLevelName).name(settings)).tag(
+ CollectionPickerOption.topLevel(topLevelName)
+ )
}
- ForEach(settings.folders, id: \.id) { folder in
+ ForEach(
+ settings.folders.filter { folder in
+ folder.topLevelName == nil
+ || (selectedCollectionOption == .topLevel(folder.topLevelName!)
+ && folder.topLevelName != nil)
+ }, id: \.id
+ ) { folder in
if isCollectionPopulated(folder.id) {
- Text(folder.name).tag(folder.id)
+ Text(CollectionPickerOption.folder(folder.id).name(settings)).tag(
+ CollectionPickerOption.folder(folder.id)
+ )
}
}
}
@@ -199,16 +233,35 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { // swi
}
Menu {
- Picker("Collection", selection: $selectedFolder) {
- Text("All").tag(nil as UUID?)
+ Picker("Collection", selection: $selectedCollectionOption) {
+ Text(CollectionPickerOption.all.name(settings)).tag(CollectionPickerOption.all)
if items.contains(where: { $0.folder == nil }) {
- Text("Uncategorised").tag(UUID.nilUUID())
+ Text(CollectionPickerOption.uncategorized.name(settings)).tag(
+ CollectionPickerOption.uncategorized
+ )
+ }
+
+ ForEach(
+ settings.folders
+ .filter { $0.topLevelName != nil }
+ .map { $0.topLevelName! }
+ .removingDuplicates(), id: \.self
+ ) { topLevelName in
+ Text(CollectionPickerOption.topLevel(topLevelName).name(settings)).tag(
+ CollectionPickerOption.topLevel(topLevelName)
+ )
}
- ForEach(settings.folders, id: \.id) { folder in
- Text(folder.name)
- .tag(folder.id)
+ ForEach(
+ settings.folders.filter { folder in
+ folder.topLevelName == nil
+ || (selectedCollectionOption == .topLevel(folder.topLevelName!)
+ && folder.topLevelName != nil)
+ }, id: \.id
+ ) { folder in
+ Text(CollectionPickerOption.folder(folder.id).name(settings))
+ .tag(CollectionPickerOption.folder(folder.id))
.selectionDisabled(!isCollectionPopulated(folder.id))
}
}