From dce5af8a890f47a617be30a68f008ff7b06e8d62 Mon Sep 17 00:00:00 2001 From: John Burwell Date: Fri, 29 May 2026 13:44:25 -0500 Subject: [PATCH] Decouple source access from detail view types --- .../Models/Content/DirectoryEntry.swift | 7 +++++++ .../Services/Sources/Core/SourceLibrary.swift | 2 +- .../AppleMobileDeviceSourceAccess.swift | 4 ++-- .../SourceAccess/Core/SourceAccessCoordinator.swift | 6 +++--- .../LocalFolder/LocalFolderSourceAccess.swift | 4 ++-- .../UI/Detail/ItemDetailColumnViews.swift | 8 +------- .../UI/Detail/ItemDetailView.swift | 2 +- .../UI/Preview/PreviewFixtures.swift | 10 +++++----- World Manager for Minecraft/UI/Root/ContentView.swift | 2 +- 9 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 World Manager for Minecraft/Models/Content/DirectoryEntry.swift diff --git a/World Manager for Minecraft/Models/Content/DirectoryEntry.swift b/World Manager for Minecraft/Models/Content/DirectoryEntry.swift new file mode 100644 index 0000000..4572253 --- /dev/null +++ b/World Manager for Minecraft/Models/Content/DirectoryEntry.swift @@ -0,0 +1,7 @@ +import Foundation + +struct DirectoryEntry: Identifiable, Hashable, Sendable { + let id = UUID() + let name: String + let isDirectory: Bool +} diff --git a/World Manager for Minecraft/Services/Sources/Core/SourceLibrary.swift b/World Manager for Minecraft/Services/Sources/Core/SourceLibrary.swift index 0e4306f..c1f47a0 100644 --- a/World Manager for Minecraft/Services/Sources/Core/SourceLibrary.swift +++ b/World Manager for Minecraft/Services/Sources/Core/SourceLibrary.swift @@ -187,7 +187,7 @@ final class SourceLibrary: ObservableObject, SourceScanSessionHosting, SourcePer startScan(for: sourceID, mode: .fullScan) } - func listContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] { + func listContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] { try await sourceAccessMethod.listItemContents(for: item, in: source) } diff --git a/World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift b/World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift index f0a00d8..f3f675b 100644 --- a/World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift +++ b/World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift @@ -307,7 +307,7 @@ struct AppleMobileDeviceSourceAccess: ConnectedDeviceSourceAccessMethod { } } - nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] { + nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] { guard case .connectedDevice(_, let container) = source.origin else { return [] } @@ -325,7 +325,7 @@ struct AppleMobileDeviceSourceAccess: ConnectedDeviceSourceAccessMethod { return entries .map { entry in let isDirectory = !NSString(string: entry).pathExtension.isEmpty ? false : true - return DirectoryPreviewEntry(name: entry, isDirectory: isDirectory) + return DirectoryEntry(name: entry, isDirectory: isDirectory) } .sorted { lhs, rhs in if lhs.isDirectory != rhs.isDirectory { diff --git a/World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift b/World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift index a8d915f..777b7ea 100644 --- a/World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift +++ b/World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift @@ -26,7 +26,7 @@ protocol SourceAccessMethod: Sendable { nonisolated func loadPreviewAssets(for items: [MinecraftContentItem], in source: MinecraftSource) async -> [MinecraftContentItem] nonisolated func loadSize(for item: MinecraftContentItem, in source: MinecraftSource) async -> MinecraftContentItem nonisolated func loadSizeAssets(for items: [MinecraftContentItem], in source: MinecraftSource) async -> [MinecraftContentItem] - nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] + nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] nonisolated func materializeItem(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> URL nonisolated func purgeCachedArtifacts(for source: MinecraftSource) async } @@ -96,7 +96,7 @@ extension SourceAccessMethod { return sizedItems } - nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] { + nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] { _ = source _ = item return [] @@ -191,7 +191,7 @@ struct SourceAccessCoordinator: SourceAccessMethod { return await accessMethod(for: source).loadSizeAssets(for: items, in: source) } - nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] { + nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] { return try await accessMethod(for: source).listItemContents(for: item, in: source) } diff --git a/World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift b/World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift index c7cbd93..2080508 100644 --- a/World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift +++ b/World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift @@ -104,7 +104,7 @@ struct LocalFolderSourceAccess: SourceAccessMethod { return WorldScanner.loadSize(for: item) } - nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryPreviewEntry] { + nonisolated func listItemContents(for item: MinecraftContentItem, in source: MinecraftSource) async throws -> [DirectoryEntry] { _ = source let fileManager = FileManager.default let urls = try fileManager.contentsOfDirectory( @@ -116,7 +116,7 @@ struct LocalFolderSourceAccess: SourceAccessMethod { return urls .map { url in let isDirectory = (try? url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) == true - return DirectoryPreviewEntry(name: url.lastPathComponent, isDirectory: isDirectory) + return DirectoryEntry(name: url.lastPathComponent, isDirectory: isDirectory) } .sorted { lhs, rhs in if lhs.isDirectory != rhs.isDirectory { diff --git a/World Manager for Minecraft/UI/Detail/ItemDetailColumnViews.swift b/World Manager for Minecraft/UI/Detail/ItemDetailColumnViews.swift index 6a9f707..5fae8b9 100644 --- a/World Manager for Minecraft/UI/Detail/ItemDetailColumnViews.swift +++ b/World Manager for Minecraft/UI/Detail/ItemDetailColumnViews.swift @@ -1,12 +1,6 @@ import AppKit import SwiftUI -struct DirectoryPreviewEntry: Identifiable { - let id = UUID() - let name: String - let isDirectory: Bool -} - struct ItemDetailColumnView: View { let item: MinecraftContentItem? let source: MinecraftSource? @@ -16,7 +10,7 @@ struct ItemDetailColumnView: View { let worldsUsingPack: [MinecraftContentItem] let backingPackInstances: [MinecraftContentItem] let isSuspiciousPack: Bool - let contents: [DirectoryPreviewEntry] + let contents: [DirectoryEntry] let directoryPreviewLimit: Int let isEmpty: Bool let isPerformingItemAction: Bool diff --git a/World Manager for Minecraft/UI/Detail/ItemDetailView.swift b/World Manager for Minecraft/UI/Detail/ItemDetailView.swift index acb7486..16257ce 100644 --- a/World Manager for Minecraft/UI/Detail/ItemDetailView.swift +++ b/World Manager for Minecraft/UI/Detail/ItemDetailView.swift @@ -12,7 +12,7 @@ struct ItemDetailView: View { let worldsUsingPack: [MinecraftContentItem] let backingPackInstances: [MinecraftContentItem] let isSuspiciousPack: Bool - let contents: [DirectoryPreviewEntry] + let contents: [DirectoryEntry] let directoryPreviewLimit: Int let isPerformingItemAction: Bool let areFileActionsEnabled: Bool diff --git a/World Manager for Minecraft/UI/Preview/PreviewFixtures.swift b/World Manager for Minecraft/UI/Preview/PreviewFixtures.swift index 63060ce..23be141 100644 --- a/World Manager for Minecraft/UI/Preview/PreviewFixtures.swift +++ b/World Manager for Minecraft/UI/Preview/PreviewFixtures.swift @@ -230,11 +230,11 @@ enum PreviewFixtures { static let allSources = [primarySource, secondarySource] static let directoryEntries = [ - DirectoryPreviewEntry(name: "db", isDirectory: true), - DirectoryPreviewEntry(name: "level.dat", isDirectory: false), - DirectoryPreviewEntry(name: "levelname.txt", isDirectory: false), - DirectoryPreviewEntry(name: "world_icon.jpeg", isDirectory: false), - DirectoryPreviewEntry(name: "resource_packs", isDirectory: true) + DirectoryEntry(name: "db", isDirectory: true), + DirectoryEntry(name: "level.dat", isDirectory: false), + DirectoryEntry(name: "levelname.txt", isDirectory: false), + DirectoryEntry(name: "world_icon.jpeg", isDirectory: false), + DirectoryEntry(name: "resource_packs", isDirectory: true) ] } diff --git a/World Manager for Minecraft/UI/Root/ContentView.swift b/World Manager for Minecraft/UI/Root/ContentView.swift index 64dae2f..d53b987 100644 --- a/World Manager for Minecraft/UI/Root/ContentView.swift +++ b/World Manager for Minecraft/UI/Root/ContentView.swift @@ -19,7 +19,7 @@ struct ContentView: View { @State private var isPerformingItemAction = false @State private var isShowingDeviceSourceSheet = false @State private var sortMode: ItemSortMode = .name - @State private var directoryPreviewContents: [DirectoryPreviewEntry] = [] + @State private var directoryPreviewContents: [DirectoryEntry] = [] private let connectedDeviceAccess: AppleMobileDeviceSourceAccess private let deviceSourceFactory: ConnectedDeviceSourceFactory