Update design docs
This commit is contained in:
parent
cbcbf85538
commit
5562389b1c
@ -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://<device-udid>/<bundle-id>?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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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`.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user