Add outbound source capabilities model
This commit is contained in:
parent
e6f529e0fc
commit
58ed0ca7ca
@ -13,6 +13,7 @@ struct MinecraftSource: Identifiable, Hashable, Sendable {
|
||||
var origin: MinecraftSourceOrigin
|
||||
var accessDescriptor: SourceAccessDescriptor
|
||||
var availability: SourceAvailability
|
||||
var capabilities: SourceCapabilities
|
||||
var bookmarkData: Data?
|
||||
var displayName: String
|
||||
var displayItems: [MinecraftContentItem]
|
||||
@ -56,6 +57,7 @@ struct MinecraftSource: Identifiable, Hashable, Sendable {
|
||||
refreshStrategy: resolvedOrigin.defaultRefreshStrategy
|
||||
)
|
||||
self.availability = availability
|
||||
self.capabilities = resolvedOrigin.defaultCapabilities
|
||||
self.bookmarkData = bookmarkData
|
||||
self.displayName = normalizedFolderURL.lastPathComponent
|
||||
self.displayItems = []
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
//
|
||||
// SourceCapabilities.swift
|
||||
// World Manager for Minecraft
|
||||
//
|
||||
// Created by OpenAI on 2026-05-29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct SourceCapabilities: Hashable, Sendable, Codable {
|
||||
var canScan: Bool = true
|
||||
var canMaterializeItems: Bool = true
|
||||
var canExportPortablePackages: Bool = true
|
||||
|
||||
static let localFolder = SourceCapabilities(
|
||||
canScan: true,
|
||||
canMaterializeItems: true,
|
||||
canExportPortablePackages: true
|
||||
)
|
||||
|
||||
static let connectedDevice = SourceCapabilities(
|
||||
canScan: true,
|
||||
canMaterializeItems: true,
|
||||
canExportPortablePackages: true
|
||||
)
|
||||
}
|
||||
@ -77,6 +77,15 @@ nonisolated enum MinecraftSourceOrigin: Hashable, Sendable, Codable {
|
||||
return .staged
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated var defaultCapabilities: SourceCapabilities {
|
||||
switch self {
|
||||
case .localFolder:
|
||||
return .localFolder
|
||||
case .connectedDevice:
|
||||
return .connectedDevice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated enum MinecraftSourceKind: String, Hashable, Sendable, Codable {
|
||||
|
||||
@ -131,6 +131,7 @@ final class SourceLibrary: ObservableObject, SourceScanSessionHosting, SourcePer
|
||||
source.bookmarkData = bookmarkData
|
||||
}
|
||||
source.accessDescriptor = sourceAccessMethod.accessDescriptor(for: source)
|
||||
source.capabilities = source.origin.defaultCapabilities
|
||||
}
|
||||
startScan(for: normalizedURL, mode: .fullScan)
|
||||
return normalizedURL
|
||||
@ -155,6 +156,7 @@ final class SourceLibrary: ObservableObject, SourceScanSessionHosting, SourcePer
|
||||
existingSource.origin = source.origin
|
||||
existingSource.accessDescriptor = source.accessDescriptor
|
||||
existingSource.availability = source.availability
|
||||
existingSource.capabilities = source.capabilities
|
||||
if existingSource.bookmarkData == nil {
|
||||
existingSource.bookmarkData = source.bookmarkData
|
||||
}
|
||||
@ -165,6 +167,7 @@ final class SourceLibrary: ObservableObject, SourceScanSessionHosting, SourcePer
|
||||
} else {
|
||||
var resolvedSource = source
|
||||
resolvedSource.accessDescriptor = sourceAccessMethod.accessDescriptor(for: resolvedSource)
|
||||
resolvedSource.capabilities = resolvedSource.origin.defaultCapabilities
|
||||
sources.append(resolvedSource)
|
||||
sources.sort { $0.displayName.localizedStandardCompare($1.displayName) == .orderedAscending }
|
||||
}
|
||||
|
||||
@ -45,6 +45,11 @@ struct AppleMobileDeviceSourceAccess: ConnectedDeviceSourceAccessMethod {
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated func capabilities(for source: MinecraftSource) async -> SourceCapabilities {
|
||||
_ = source
|
||||
return .connectedDevice
|
||||
}
|
||||
|
||||
nonisolated func listConnectedDevices() async throws -> [ConnectedDevice] {
|
||||
let devices = try await AppleMobileDeviceAccess.connectedDevices()
|
||||
return devices.compactMap { device in
|
||||
|
||||
@ -16,6 +16,7 @@ protocol SourceAccessMethod: Sendable {
|
||||
nonisolated var accessorIdentifier: SourceAccessorIdentifier { get }
|
||||
nonisolated func accessDescriptor(for source: MinecraftSource) -> SourceAccessDescriptor
|
||||
nonisolated func availability(for source: MinecraftSource) async -> SourceAvailability
|
||||
nonisolated func capabilities(for source: MinecraftSource) async -> SourceCapabilities
|
||||
nonisolated func discoverItems(
|
||||
for source: MinecraftSource,
|
||||
mode: SourceDiscoveryMode,
|
||||
@ -49,6 +50,10 @@ extension SourceAccessMethod {
|
||||
return .unknown
|
||||
}
|
||||
|
||||
nonisolated func capabilities(for source: MinecraftSource) async -> SourceCapabilities {
|
||||
source.origin.defaultCapabilities
|
||||
}
|
||||
|
||||
nonisolated func discoverItems(
|
||||
for source: MinecraftSource,
|
||||
mode: SourceDiscoveryMode,
|
||||
@ -171,6 +176,10 @@ struct SourceAccessCoordinator: SourceAccessMethod {
|
||||
return await accessMethod(for: source).availability(for: source)
|
||||
}
|
||||
|
||||
nonisolated func capabilities(for source: MinecraftSource) async -> SourceCapabilities {
|
||||
return await accessMethod(for: source).capabilities(for: source)
|
||||
}
|
||||
|
||||
nonisolated func enrich(_ item: MinecraftContentItem, for source: MinecraftSource) async -> MinecraftContentItem {
|
||||
return await accessMethod(for: source).enrich(item, for: source)
|
||||
}
|
||||
|
||||
@ -43,6 +43,11 @@ struct LocalFolderSourceAccess: SourceAccessMethod {
|
||||
return FileManager.default.fileExists(atPath: candidateURL.path) ? .available : .unavailable
|
||||
}
|
||||
|
||||
nonisolated func capabilities(for source: MinecraftSource) async -> SourceCapabilities {
|
||||
_ = source
|
||||
return .localFolder
|
||||
}
|
||||
|
||||
nonisolated func discoverItems(
|
||||
for source: MinecraftSource,
|
||||
mode: SourceDiscoveryMode,
|
||||
|
||||
@ -12,6 +12,33 @@ import Testing
|
||||
@MainActor
|
||||
struct World_Manager_for_MinecraftTests {
|
||||
|
||||
@Test func sourceOriginsExposeOutboundCapabilities() async throws {
|
||||
let localSource = MinecraftSource(folderURL: URL(fileURLWithPath: "/tmp/local"))
|
||||
#expect(localSource.capabilities == .localFolder)
|
||||
|
||||
let device = ConnectedDevice(
|
||||
udid: "device",
|
||||
name: "Device",
|
||||
productType: nil,
|
||||
osVersion: nil,
|
||||
connection: .usb,
|
||||
trustState: .trusted
|
||||
)
|
||||
let container = DeviceAppContainer(
|
||||
deviceUDID: device.udid,
|
||||
appID: "com.mojang.minecraftpe",
|
||||
appName: "Minecraft",
|
||||
accessMode: .documents,
|
||||
minecraftFolderRelativePath: "Documents/games/com.mojang"
|
||||
)
|
||||
let deviceSource = MinecraftSource(
|
||||
folderURL: URL(fileURLWithPath: "/tmp/device"),
|
||||
origin: .connectedDevice(device: device, container: container)
|
||||
)
|
||||
|
||||
#expect(deviceSource.capabilities == .connectedDevice)
|
||||
}
|
||||
|
||||
@Test func packIdentityUsesUUIDAndVersion() async throws {
|
||||
let first = PackIdentity(
|
||||
type: .behaviorPack,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user