diff --git a/docs/ios-device-access.md b/docs/ios-device-access.md index 1aec0e4..d9bcfd8 100644 --- a/docs/ios-device-access.md +++ b/docs/ios-device-access.md @@ -1,136 +1,105 @@ -# iOS Device Access Notes +# Connected iOS Device Access ## Summary -This project can now read Minecraft Bedrock content directly from a connected iPhone or iPad on macOS using `MobileDevice.framework` and House Arrest. +World Manager can browse Minecraft Bedrock content from a trusted iPhone or iPad on macOS using Apple's private `MobileDevice.framework` and the House Arrest service. -The app does **not** scan the device live through custom file APIs. Instead, it: +Connected-device sources are modeled as normal `MinecraftSource` values, but they are not scanned through a live filesystem mirror. The current implementation asks the device for library item summaries, metadata, icons, sizes, and directory listings through `AppleMobileDeviceSourceAccess`. Only explicit materialization operations, such as reveal/export/share, mirror an item subtree into a temporary local directory. -1. Detects a connected trusted device with `MobileDevice.framework`. -2. Opens House Arrest for `com.mojang.minecraftpe`. -3. Uses `VendDocuments`. -4. Mirrors the proven Minecraft subtree into a temporary local folder. -5. Hands that local folder to the existing `WorldScanner`. +## Current Flow -That keeps the rest of the app filesystem-based. +1. `SourceLibrary` owns a `ConnectedDeviceRuntime` refresh loop when a connected-device access method is configured. +2. `AppleMobileDeviceSourceAccess.listConnectedDevices()` enumerates devices through `AppleMobileDeviceAccess.connectedDevices()`. +3. `AppleMobileDeviceSourceAccess.listAccessibleContainers(for:)` lists app containers and prioritizes `com.mojang.minecraftpe`. +4. `ConnectedDeviceSourcePickerView` lets the user add a device-backed Minecraft source. +5. `ConnectedDeviceSourceFactory` creates a stable synthetic source identifier: -## Proven Findings + ```text + wmminecraft-device:///?mode=documents + ``` -### Correct bundle ID +6. `SourceScanExecutor` scans the source through the generic `SourceAccessMethod` protocol. +7. `AppleMobileDeviceSourceAccess.discoverItems` calls `minecraftLibrarySnapshot` for item summaries and `minecraftMetadataBatch` for metadata. +8. Preview icons, size metrics, directory contents, and full item materialization are loaded lazily through the same source-access method. -Minecraft on the tested device is: +This keeps UI, indexing, export, and persistence mostly source-agnostic while allowing connected devices to avoid a full upfront mirror. -- `com.mojang.minecraftpe` +## Minecraft Container -### App metadata +The tested Minecraft bundle identifier is: -The app record reported: +```text +com.mojang.minecraftpe +``` -- `UIFileSharingEnabled = 1` -- `LSSupportsOpeningDocumentsInPlace = 1` +Minecraft exposes a vendable Documents surface. The working Minecraft content root for House Arrest `VendDocuments` is: -So Minecraft does expose a vendable Documents surface. +```text +Documents/games/com.mojang +``` -### Correct vend root +The app treats that value as a vend-relative path stored on `DeviceAppContainer.minecraftFolderRelativePath`. -House Arrest `VendDocuments` succeeds, but the Minecraft content is **not** rooted at: +Expected subfolders under that root: -- `games/com.mojang` +- `minecraftWorlds` +- `resource_packs` +- `behavior_packs` +- `skin_packs` +- `world_templates` -The proven path is: +## House Arrest Details -- `Documents/games/com.mojang` +The implementation uses the explicit House Arrest flow in the Objective-C bridge: -### Proven subfolders +1. Start `com.apple.mobile.house_arrest`. +2. Send `VendDocuments`. +3. Receive the vend response. +4. Use AFC against the returned service connection. -These paths were verified through AFC on the real device: +The direct `AMDeviceCreateHouseArrestService` helper returned `InstallationLookupFailed` / `e80000b7` on the tested device, so it is not the primary path. -- `Documents/games/com.mojang/minecraftWorlds` -- `Documents/games/com.mojang/resource_packs` -- `Documents/games/com.mojang/behavior_packs` -- `Documents/games/com.mojang/world_templates` +The AFC root for this vend should not be treated as a normal `/` filesystem root. Paths are relative to the vend surface, and Minecraft content is reached through `Documents/games/com.mojang`. -## Important API Findings +## Runtime Behavior -### `AMDeviceCreateHouseArrestService` +Connected-device sources use a staged refresh strategy: -The direct helper path still returned a device-side error on the tested device: +- Availability is derived from current device presence and trust state. +- Trusted devices are available. +- Locked or untrusted devices are limited. +- Missing or inaccessible devices are disconnected. +- When a source becomes available, `SourceSyncRuntime` can queue a reconcile scan instead of a full scan if cached content exists. -- `InstallationLookupFailed` -- `e80000b7` +Scan execution uses fewer workers for connected-device sources than local folders to avoid overloading AFC/MobileDevice calls. -So the app currently relies on the explicit vend flow instead: +During scan: -1. `AMDeviceSecureStartService("com.apple.mobile.house_arrest")` -2. `AMDServiceConnectionSendMessage` with `VendDocuments` -3. `AMDServiceConnectionReceiveMessage` -4. Create AFC from the returned service connection +- `minecraftLibrarySnapshot` returns candidate content items. +- `minecraftMetadataBatch` returns display names, UUIDs, versions, minimum engine versions, and world pack references. +- Icons are loaded with `minecraftIconBatch` or individual file reads and cached through `ImageCacheStore`. +- Size information is loaded through `pathMetricsBatch`. +- Directory previews call `listDirectory`. -### `VendDocuments` vs `VendContainer` +During materialization: -`VendDocuments` is the working path for Minecraft on the tested device. +- `materializeItem` mirrors one remote item subtree into `NSTemporaryDirectory()/WMMConnectedDeviceReveal/...`. +- `ContentPackageExporter` mirrors the selected item into archive staging when exporting connected-device content. +- Temporary materialized folders are treated as disposable. -### AFC path behavior +## Persistence -The AFC root is not a normal `/` root for this vend. Examples: +Connected-device sources are persisted in the SQLite source cache with: -- `"/"` returned AFC status `0xA` -- `"/games/com.mojang"` returned AFC status `0x8` -- `"Documents/games/com.mojang"` worked +- source identifier +- source origin and device/container metadata +- access descriptor +- availability +- raw item cache +- source snapshot +- last scan date -So code should use the proven vend-relative path instead of assuming a container root layout. - -## Current Project Shape - -## Source Access Architecture - -Source intake is now organized around access methods rather than one-off services. - -- `SourceAccess/Core` - - shared contracts and the `SourceAccessCoordinator` -- `SourceAccess/LocalFolder` - - the local disk access method -- `SourceAccess/ConnectedDevice` - - connected-device source creation and picker UI -- `SourceAccess/ConnectedDevice/AppleMobileDevice` - - the built-in Apple mobile-device transport - -The key abstraction is `SourceAccessMethod`. - -Each access method is responsible for: - -1. turning a `MinecraftSource` into a local `PreparedScanRoot` -2. cleaning up that prepared root when scanning finishes - -That keeps the rest of the app indifferent to how a source is reached. - -### App path - -User flow: - -- `SourcesSidebarView` opens the connected-device sheet. -- `ConnectedDeviceSourcePickerView` lets the user select a device/app and a subpath. -- `AppleMobileDeviceSourceAccess` is the active connected-device access method. - -### Scan-root preparation - -`SourceAccessCoordinator` chooses between: - -- local folder sources -- connected device sources - -For connected devices: - -- the built-in `AppleMobileDeviceSourceAccess` -- future connected-device access methods can implement the same contracts - -### Mirror behavior - -The MobileDevice fallback: - -- mirrors the subtree into a temporary directory -- returns that directory as `PreparedScanRoot.rootURL` -- cleans it up with `CleanupBehavior.deleteTemporaryDirectory` +On app launch, cached sources and items are restored before availability refreshes complete, so offline device-backed sources can still show cached results. ## Relevant Files @@ -138,19 +107,14 @@ The MobileDevice fallback: - `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceBridge.h` - `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceAccess.swift` - `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift` -- `World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift` -- `World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift` -- `World Manager for Minecraft/Models/SourceOrigin.swift` +- `World Manager for Minecraft/SourceAccess/ConnectedDevice/ConnectedDeviceSourceFactory.swift` - `World Manager for Minecraft/SourceAccess/ConnectedDevice/ConnectedDeviceSourcePickerView.swift` +- `World Manager for Minecraft/Services/Sources/ConnectedDevice/SourceConnectedDeviceRuntime.swift` +- `World Manager for Minecraft/Services/Sources/Scanning/SourceScanExecution.swift` -## Developer CLI +## Developer Probe -A local probe harness was added for iteration: - -- `Scripts/run_mobile_device_probe.sh` -- `Tools/mobile_device_probe.m` - -Useful commands: +The local probe harness is useful for debugging MobileDevice behavior outside the app: ```sh Scripts/run_mobile_device_probe.sh summary @@ -160,18 +124,11 @@ Scripts/run_mobile_device_probe.sh probe-paths com.mojang.minecraftpe Scripts/run_mobile_device_probe.sh mirror com.mojang.minecraftpe 'Documents/games/com.mojang' /tmp/wmm-minecraft-device-mirror ``` -These commands generally need to run outside the agent sandbox to access the real connected device. +These commands require a trusted connected device and generally need to run outside restricted automation sandboxes. -## Known Cleanup Targets +## Caveats -Not part of the device-access implementation itself: - -- `layoutSubtreeIfNeeded` warning: SwiftUI/AppKit layout issue -- `duplicate column name: bookmark_data`: persistence migration issue -- preview actor-isolation warnings in `PreviewFixtures.swift` - -## Recommendation - -Keep the CLI probe and this document. - -They provide a reproducible path for future device-access debugging without going back through GUI-based experimentation. +- `MobileDevice.framework`, House Arrest, and AFC are private Apple interfaces. +- Behavior can change across macOS, iOS, iPadOS, and Minecraft releases. +- Device access requires trust, unlock state, and a vendable app container. +- Connected-device export/reveal operations may be slower than local folder operations because they materialize remote content on demand. diff --git a/docs/library-intelligence-notes.md b/docs/library-intelligence-notes.md index caf8e9b..5a600a0 100644 --- a/docs/library-intelligence-notes.md +++ b/docs/library-intelligence-notes.md @@ -1,117 +1,201 @@ -# Library Intelligence Notes +# Library Architecture and Future Intelligence -## Focus Areas +## Current Architecture -- Cross-library search across all scanned sources, not just the currently selected library. -- Smart folders as saved queries over indexed content. -- Automated analysis that surfaces outliers, integrity issues, and duplicates. -- File operations for moving, copying, backing up, and restoring Minecraft content across sources. +The app is organized around source-agnostic Minecraft libraries. A source can be a local folder or a connected iOS/iPadOS device, but the UI mostly interacts with the same `MinecraftSource` and `MinecraftContentItem` models for both. -## File Operations +The main runtime owner is `SourceLibrary`: -Core operations: +- Stores visible sources and connected-device sidebar entries. +- Starts and cancels scans. +- Restores/persists cached sources. +- Refreshes source availability. +- Builds item lookup indexes for selection and file actions. +- Routes filesystem-like operations through `SourceAccessMethod`. -- Copy a world from one library to another. -- Copy packs or templates between libraries. -- Export selected items as archives. -- Import archives or folders into a target library. -- Back up an entire accessible Minecraft library from a device or folder source. -- Restore items from a backup into a chosen target source. +`ContentView` renders the three-column app: -Operational concerns: +- source/device sidebar +- projected item list +- detail/metadata/action column -- Detect duplicate world or pack identities before writing. -- Handle naming conflicts with overwrite, rename, or skip behavior. -- Validate that the destination source supports the content being copied. -- Show progress for long-running copy or backup work. -- Keep operations source-agnostic where possible so local folders, connected devices, and removable media can share the same workflow. +The item list is built from an `ItemCollectionProjectionRequest` and generated off the main actor by `ItemCollectionProjector`. -Future file-operation ideas: +## Source Access -- Batch copy selected worlds or packs. -- Sync or compare two libraries before copying. -- One-click backup of a connected device's Minecraft content. -- Backup manifests so backups remain browsable and restorable later. -- Restore preview showing what will be created or overwritten. +`SourceAccessMethod` is the boundary between source-specific I/O and source-independent app behavior. -## Cross-Library Search +The protocol covers: -Goals: +- access descriptor +- availability +- capabilities +- discovery +- enrichment +- preview assets +- size loading +- directory listing +- item materialization +- cache cleanup -- Search across every scanned source in one place. -- Show which library or device each result came from. -- Keep search useful even when some device-backed sources are offline by using cached scan results where possible. +Implemented access methods: -Useful filters: +- `LocalFolderSourceAccess` + - resolves security-scoped bookmarks + - scans local Minecraft folders with `WorldScanner` + - reads local directory listings + - returns native folder URLs for materialization -- Content type: worlds, behavior packs, resource packs, skin packs, templates. -- Source kind: local folders, connected devices, removable media. -- Source name or device name. -- Health state: complete, partial metadata, broken, unresolved references. -- Size ranges and date ranges. +- `AppleMobileDeviceSourceAccess` + - enumerates devices and app containers through MobileDevice + - discovers Minecraft content through device summaries and metadata batches + - loads icons, sizes, and directory contents on demand + - materializes device items by mirroring one subtree to a temporary directory -Useful result metadata: +`ContentViewDependencies.makeDefault()` wires `SourceLibrary` with a `SourceAccessCoordinator` that dispatches between local-folder access and Apple MobileDevice access. -- Display name. -- Source name. -- Content type. -- Size. -- Last played or modified date. -- Availability state for the backing source. +## Scanning Pipeline -## Smart Folders +`SourceScanExecutor` runs source scans in stages: -Definition: +1. Mark source as scanning and update availability. +2. Start a `WorldScanner` scan session. +3. Discover items through the source-access method. +4. Feed discovered items into `SourceIndexActor`. +5. Enrich metadata through worker tasks. +6. Build and publish normalized index snapshots. +7. Load preview assets. +8. Load size metrics for local sources; connected-device size loading uses a faster batched path. +9. Persist source state after major stages. +10. Update final status and send scan notifications when appropriate. -- Smart folders are saved predicates over indexed content, not physical folders on disk. +Local reconcile scans can reuse cached items for unchanged collection snapshots. Connected-device reconcile scans preserve cached collections when a device response omits a collection that was previously known. -Built-in smart folder candidates: +## Content Model -- Largest Worlds -- Largest Archives -- Recently Modified -- Recently Played -- Broken Archives -- Worlds With Missing Packs -- Duplicate Packs -- Suspicious Packs -- Offline Results -- Incomplete Metadata +The app recognizes these content types: -Future direction: +- worlds: `minecraftWorlds` +- behavior packs: `behavior_packs` +- resource packs: `resource_packs` +- skin packs: `skin_packs` +- world templates: `world_templates` -- Allow users to create custom smart folders from filters and sort rules. +`MinecraftContentItem` stores: -## Automated Analysis +- stable folder URL identity +- content type and collection root +- display name and icon +- dates and size +- pack UUID/version/engine metadata +- world metadata from `level.dat` +- pack references +- metadata/preview/size loading flags -Potential analyses: +`WorldScanner` handles local folder discovery and enrichment: -- Largest content items by size. -- Broken archives or invalid package structures. -- Worlds missing `level.dat` or other expected files. -- Worlds with unresolved pack references. -- Duplicate packs across libraries by UUID and version. -- Diverged duplicates that appear related but differ in size, modified date, or fingerprint. -- Orphaned packs not referenced by any world. -- Changes since the last scan. +- finds candidate collection folders +- detects embedded behavior/resource packs inside worlds +- reads `levelname.txt`, `manifest.json`, icons, and `level.dat` +- computes collection snapshots for reconcile scans -Possible outputs: +## Normalized Index -- Smart folder population. -- Sidebar badges or warnings. -- A future dashboard or “Insights” view. +`SourceContentIndexer` turns raw discovered items into normalized source data: -## Suggested Order +- `rawItems` +- `logicalPacks` +- `logicalWorlds` +- `packInstances` +- `worldPackRelationships` +- `displayItems` +- content-type counts -1. Add global search across all scanned libraries. -2. Add a small set of built-in smart folders. -3. Add integrity and duplicate analysis to feed those folders. -4. Add custom smart folders later if the built-ins prove useful. +Packs are grouped by `PackIdentity` using UUID/version when available, or fallback name/location when metadata is incomplete. A representative pack is chosen for display, preferring top-level packs over embedded world copies, loaded metadata, icons, recent modified dates, and stable path ordering. -## Product Notes +World relationships resolve pack references to logical packs when possible. Unresolved references remain visible on the world detail side. -- “Search” solves retrieval. -- “Smart folders” solve recurring saved views. -- “Analysis” solves discovery and problem finding. +The displayed item list uses worlds, representative packs, skin packs, and templates. Embedded duplicate pack instances remain available through detail views. -These should stay distinct in the product even if they share the same underlying index. +## Persistence and Offline Cache + +`SourcePersistenceStore` stores source cache data in SQLite under Application Support: + +```text +Library/Application Support/World Manager for Minecraft/LibraryCache-v2026-05-28.sqlite +``` + +Persisted records include: + +- source ID and folder URL +- source origin +- access descriptor +- availability +- bookmark data +- display name +- raw item payloads +- source snapshots +- last scan date + +`SourcePersistenceCoordinator` restores sources at launch, applies cached images, repairs older records when needed, refreshes availability, then schedules reconcile scans when cached data may be stale. + +This is what allows disconnected device-backed sources to display cached results. + +## File Actions + +File operations are currently focused on export, share, reveal/materialize, and directory preview: + +- `ContentItemActionService` provides filenames, archive types, archive creation, and persistence of external representations. +- `ContentPackageExporter` stages content and creates ZIP-based Minecraft package archives through `/usr/bin/ditto`. +- Local source items can use native folders directly. +- Connected-device items are mirrored into temporary staging before export or reveal. + +Archive extensions: + +- worlds -> `.mcworld` +- behavior/resource/skin packs -> `.mcpack` +- world templates -> `.mctemplate` + +## Current Product Capabilities + +Implemented: + +- Browse multiple local and connected-device sources. +- Restore cached sources at launch. +- Reconcile source changes. +- Search within the selected source/list projection. +- Sort by name, modified/last-played date, or size. +- Inspect world and pack metadata. +- Resolve world-to-pack relationships when metadata allows. +- Show embedded and backing pack instances. +- Export/share/reveal items. +- Preview package files with Quick Look. + +Not implemented yet: + +- Global cross-source search. +- User-created smart folders. +- Dedicated duplicate/integrity dashboard. +- Backup/restore workflows as first-class operations. +- Cross-source copy/move/import workflows. + +## Future Intelligence Direction + +The existing normalized index provides most of the data needed for richer library intelligence. Future work should build on `SourceContentIndexer`, persisted source caches, and projection requests rather than introducing a separate scanning path. + +Useful next features: + +- Global search across all visible and cached sources. +- Built-in smart folders for large worlds, recent worlds, unresolved pack references, duplicate packs, suspicious packs, and offline cached results. +- Duplicate analysis across sources by UUID/version, fallback identity, size, and modified date. +- Integrity checks for missing `level.dat`, malformed manifests, broken archives, and unresolved world pack references. +- Backup manifests that make exported backups browsable and restorable later. + +Suggested implementation order: + +1. Add a global read-only index projection over all `SourceLibrary.visibleSources`. +2. Add built-in smart folders backed by predicates over the normalized index. +3. Add cross-source duplicate and integrity analyzers. +4. Add explicit copy/backup/restore operations after analysis and conflict detection are reliable. + +Keep search, smart folders, and analysis distinct in the UI even if they share the same underlying source/index data. diff --git a/docs/quick-look-plan.md b/docs/quick-look-plan.md index d31bfe9..66cad9c 100644 --- a/docs/quick-look-plan.md +++ b/docs/quick-look-plan.md @@ -1,41 +1,126 @@ -# Quick Look Plan +# Quick Look Architecture -## Current State +## Summary -Quick Look thumbnail and preview extension targets are present in the project and share the app's Bedrock package inspection layer: +The app includes Quick Look thumbnail and preview extensions for Minecraft Bedrock package files: -- `World Manager for Minecraft/Services/MinecraftPackageInspector.swift` - - extracts `.mcworld`, `.mcpack`, `.mctemplate`, and `.mcaddon` - - normalizes archives with either flat contents or a single nested top-level folder - - infers pack type for ambiguous `.mcpack` and `.mcaddon` archives -- `World Manager for Minecraft/Services/MinecraftContentMetadataReader.swift` - - shared manifest, icon, display-name, and world metadata parsing -- `World Manager for Minecraft/QuickLook/MinecraftPackageTypes.swift` - - central UTType identifiers and extension definitions -- `World Manager for Minecraft/QuickLook/MinecraftPackageQuickLookModel.swift` - - preview-friendly summary model -- `World Manager for Minecraft/QuickLook/MinecraftPackageThumbnailRenderer.swift` - - branded thumbnail rendering with icon fallback +- `.mcworld` +- `.mcpack` +- `.mctemplate` +- `.mcaddon` + +Both extensions share the same package inspection and thumbnail rendering code used by the app target where possible. + +## Targets + +### Thumbnail Extension + +`MinecraftPackageThumbnailExtension/ThumbnailProvider.swift` + +- Implements `QLThumbnailProvider`. +- Calls `MinecraftPackageInspector.inspectArchive(at:)`. +- Renders a `CGImage` with `MinecraftPackageThumbnailRenderer`. +- Cleans up the temporary extraction directory with `MinecraftPackageInspector.cleanup`. + +### Preview Extension + +`MinecraftPackagePreviewExtension/PreviewViewController.swift` + +- Implements `QLPreviewingController`. +- Inspects the selected package archive. +- Displays the package icon when one exists. +- Falls back to the generated thumbnail artwork. +- Keeps the inspection result alive while the preview is displayed, then removes temporary extraction files in `deinit`. + +The preview is currently image-focused. `MinecraftPackageQuickLookModelBuilder` already builds structured facts, but the preview controller does not render those facts yet. + +## Shared Package Inspection + +`MinecraftPackageInspector` is the central archive reader for Quick Look: + +- Accepts `.mcworld`, `.mcpack`, `.mctemplate`, and `.mcaddon`. +- Uses `ZipArchiveReader` to inspect ZIP entries. +- Supports packages with content at the archive root or under one top-level folder. +- Extracts only metadata-relevant files into a temporary inspection directory. +- Resolves content type from extension and manifest metadata. +- Reads display name, icon, world metadata, and manifest metadata. + +Inspection results include: + +- archive URL +- temporary extraction root +- resolved content root +- content type +- display name +- icon URL +- world metadata +- manifest metadata + +Callers are responsible for cleanup. + +## Metadata Readers + +`MinecraftContentMetadataReader` provides shared metadata parsing: + +- World display names from `levelname.txt`. +- Pack display names from `manifest.json`. +- World icons from `world_icon.*`. +- Pack icons from `pack_icon.*`. +- World metadata from `level.dat` through `BedrockLevelMetadataDecoder`. +- Manifest UUID, version, and minimum engine version. +- Pack type inference for ambiguous `.mcpack` and `.mcaddon` archives. + +`MinecraftPackageQuickLookModelBuilder` converts inspection results into preview-friendly facts such as version, UUID, engine version, game mode, difficulty, last played date, seed, and Bedrock version. + +## Thumbnail Rendering + +`MinecraftPackageThumbnailRenderer` renders square thumbnail artwork: + +- If the package has an icon, it draws that icon cropped to a rounded square with a subtle border. +- If no icon is present, it draws a generated voxel-style badge with content-type-specific colors. +- Rendering is done with AppKit bitmap drawing and returns a `CGImage`. + +## Type Registration + +The main app registers exported UTTypes and document roles for Minecraft package extensions in `World-Manager-for-Minecraft-Info.plist`. + +The extension Info.plists list the same internal UTTypes under `QLSupportedContentTypes`: + +- `us.b-wells.minecraft.mcworld` +- `us.b-wells.minecraft.mcpack` +- `us.b-wells.minecraft.mctemplate` +- `us.b-wells.minecraft.mcaddon` + +## Relevant Files + +- `World-Manager-for-Minecraft-Info.plist` +- `MinecraftPackageThumbnailExtension/Info.plist` - `MinecraftPackageThumbnailExtension/ThumbnailProvider.swift` - - renders Quick Look thumbnails for supported Minecraft package files +- `MinecraftPackagePreviewExtension/Info.plist` - `MinecraftPackagePreviewExtension/PreviewViewController.swift` - - renders a basic image preview from package icons or generated thumbnail art +- `World Manager for Minecraft/QuickLook/MinecraftPackageTypes.swift` +- `World Manager for Minecraft/QuickLook/MinecraftPackageQuickLookModel.swift` +- `World Manager for Minecraft/QuickLook/MinecraftPackageThumbnailRenderer.swift` +- `World Manager for Minecraft/Services/ArchiveInspection/MinecraftPackageInspector.swift` +- `World Manager for Minecraft/Services/ArchiveInspection/MinecraftContentMetadataReader.swift` +- `World Manager for Minecraft/Services/ArchiveInspection/ZipArchiveReader.swift` -Archive inspection is covered by tests in `World Manager for MinecraftTests/World_Manager_for_MinecraftTests.swift`. +## Current Limitations -## Remaining Work +- Preview rendering shows only an image, not the structured metadata facts. +- `.mcaddon` support resolves one content root; multi-pack add-ons are not yet presented as a compound package. +- The inspector extracts only metadata files, which is intentional for Quick Look speed but means package validation is shallow. -The target layer is intentionally thin, but the preview experience can still be improved: +## Verification -- render structured metadata with `MinecraftPackageQuickLookModelBuilder` -- include: - - package icon or branded artwork - - title - - package kind - - key facts like version, UUID, minimum engine, game mode, difficulty, and last played -- add explicit UI tests or fixture-driven render tests for package previews +Run: -## Verification Notes +```sh +xcodebuild \ + -project "World Manager for Minecraft.xcodeproj" \ + -scheme "World Manager for Minecraft" \ + -configuration Debug \ + build +``` -- `xcodebuild ... build` succeeds. -- `xcodebuild ... test` should be run before release and whenever the shared archive inspection layer changes. +The unit tests cover archive inspection behavior in `World Manager for MinecraftTests/World_Manager_for_MinecraftTests.swift`.