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
|
## 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`.
|
## Current Flow
|
||||||
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`.
|
|
||||||
|
|
||||||
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`
|
Minecraft exposes a vendable Documents surface. The working Minecraft content root for House Arrest `VendDocuments` is:
|
||||||
- `LSSupportsOpeningDocumentsInPlace = 1`
|
|
||||||
|
|
||||||
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`
|
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`.
|
||||||
- `Documents/games/com.mojang/resource_packs`
|
|
||||||
- `Documents/games/com.mojang/behavior_packs`
|
|
||||||
- `Documents/games/com.mojang/world_templates`
|
|
||||||
|
|
||||||
## 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`
|
Scan execution uses fewer workers for connected-device sources than local folders to avoid overloading AFC/MobileDevice calls.
|
||||||
- `e80000b7`
|
|
||||||
|
|
||||||
So the app currently relies on the explicit vend flow instead:
|
During scan:
|
||||||
|
|
||||||
1. `AMDeviceSecureStartService("com.apple.mobile.house_arrest")`
|
- `minecraftLibrarySnapshot` returns candidate content items.
|
||||||
2. `AMDServiceConnectionSendMessage` with `VendDocuments`
|
- `minecraftMetadataBatch` returns display names, UUIDs, versions, minimum engine versions, and world pack references.
|
||||||
3. `AMDServiceConnectionReceiveMessage`
|
- Icons are loaded with `minecraftIconBatch` or individual file reads and cached through `ImageCacheStore`.
|
||||||
4. Create AFC from the returned service connection
|
- 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`
|
- source identifier
|
||||||
- `"/games/com.mojang"` returned AFC status `0x8`
|
- source origin and device/container metadata
|
||||||
- `"Documents/games/com.mojang"` worked
|
- 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.
|
On app launch, cached sources and items are restored before availability refreshes complete, so offline device-backed sources can still show cached results.
|
||||||
|
|
||||||
## 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`
|
|
||||||
|
|
||||||
## Relevant Files
|
## 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/AppleMobileDeviceBridge.h`
|
||||||
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceAccess.swift`
|
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceAccess.swift`
|
||||||
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift`
|
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/AppleMobileDevice/AppleMobileDeviceSourceAccess.swift`
|
||||||
- `World Manager for Minecraft/SourceAccess/Core/SourceAccessCoordinator.swift`
|
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/ConnectedDeviceSourceFactory.swift`
|
||||||
- `World Manager for Minecraft/SourceAccess/LocalFolder/LocalFolderSourceAccess.swift`
|
|
||||||
- `World Manager for Minecraft/Models/SourceOrigin.swift`
|
|
||||||
- `World Manager for Minecraft/SourceAccess/ConnectedDevice/ConnectedDeviceSourcePickerView.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:
|
The local probe harness is useful for debugging MobileDevice behavior outside the app:
|
||||||
|
|
||||||
- `Scripts/run_mobile_device_probe.sh`
|
|
||||||
- `Tools/mobile_device_probe.m`
|
|
||||||
|
|
||||||
Useful commands:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
Scripts/run_mobile_device_probe.sh summary
|
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
|
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:
|
- `MobileDevice.framework`, House Arrest, and AFC are private Apple interfaces.
|
||||||
|
- Behavior can change across macOS, iOS, iPadOS, and Minecraft releases.
|
||||||
- `layoutSubtreeIfNeeded` warning: SwiftUI/AppKit layout issue
|
- Device access requires trust, unlock state, and a vendable app container.
|
||||||
- `duplicate column name: bookmark_data`: persistence migration issue
|
- Connected-device export/reveal operations may be slower than local folder operations because they materialize remote content on demand.
|
||||||
- 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.
|
|
||||||
|
|||||||
@ -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.
|
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.
|
||||||
- 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.
|
|
||||||
|
|
||||||
## 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.
|
`ContentView` renders the three-column app:
|
||||||
- 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.
|
|
||||||
|
|
||||||
Operational concerns:
|
- source/device sidebar
|
||||||
|
- projected item list
|
||||||
|
- detail/metadata/action column
|
||||||
|
|
||||||
- Detect duplicate world or pack identities before writing.
|
The item list is built from an `ItemCollectionProjectionRequest` and generated off the main actor by `ItemCollectionProjector`.
|
||||||
- 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.
|
|
||||||
|
|
||||||
Future file-operation ideas:
|
## Source Access
|
||||||
|
|
||||||
- Batch copy selected worlds or packs.
|
`SourceAccessMethod` is the boundary between source-specific I/O and source-independent app behavior.
|
||||||
- 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.
|
|
||||||
|
|
||||||
## 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.
|
Implemented access methods:
|
||||||
- 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.
|
|
||||||
|
|
||||||
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.
|
- `AppleMobileDeviceSourceAccess`
|
||||||
- Source kind: local folders, connected devices, removable media.
|
- enumerates devices and app containers through MobileDevice
|
||||||
- Source name or device name.
|
- discovers Minecraft content through device summaries and metadata batches
|
||||||
- Health state: complete, partial metadata, broken, unresolved references.
|
- loads icons, sizes, and directory contents on demand
|
||||||
- Size ranges and date ranges.
|
- 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.
|
## Scanning Pipeline
|
||||||
- Source name.
|
|
||||||
- Content type.
|
|
||||||
- Size.
|
|
||||||
- Last played or modified date.
|
|
||||||
- Availability state for the backing source.
|
|
||||||
|
|
||||||
## 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
|
The app recognizes these content types:
|
||||||
- Largest Archives
|
|
||||||
- Recently Modified
|
|
||||||
- Recently Played
|
|
||||||
- Broken Archives
|
|
||||||
- Worlds With Missing Packs
|
|
||||||
- Duplicate Packs
|
|
||||||
- Suspicious Packs
|
|
||||||
- Offline Results
|
|
||||||
- Incomplete Metadata
|
|
||||||
|
|
||||||
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.
|
- finds candidate collection folders
|
||||||
- Broken archives or invalid package structures.
|
- detects embedded behavior/resource packs inside worlds
|
||||||
- Worlds missing `level.dat` or other expected files.
|
- reads `levelname.txt`, `manifest.json`, icons, and `level.dat`
|
||||||
- Worlds with unresolved pack references.
|
- computes collection snapshots for reconcile scans
|
||||||
- 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.
|
|
||||||
|
|
||||||
Possible outputs:
|
## Normalized Index
|
||||||
|
|
||||||
- Smart folder population.
|
`SourceContentIndexer` turns raw discovered items into normalized source data:
|
||||||
- Sidebar badges or warnings.
|
|
||||||
- A future dashboard or “Insights” view.
|
|
||||||
|
|
||||||
## Suggested Order
|
- `rawItems`
|
||||||
|
- `logicalPacks`
|
||||||
|
- `logicalWorlds`
|
||||||
|
- `packInstances`
|
||||||
|
- `worldPackRelationships`
|
||||||
|
- `displayItems`
|
||||||
|
- content-type counts
|
||||||
|
|
||||||
1. Add global search across all scanned libraries.
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
## Product Notes
|
World relationships resolve pack references to logical packs when possible. Unresolved references remain visible on the world detail side.
|
||||||
|
|
||||||
- “Search” solves retrieval.
|
The displayed item list uses worlds, representative packs, skin packs, and templates. Embedded duplicate pack instances remain available through detail views.
|
||||||
- “Smart folders” solve recurring saved views.
|
|
||||||
- “Analysis” solves discovery and problem finding.
|
|
||||||
|
|
||||||
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`
|
- `.mcworld`
|
||||||
- extracts `.mcworld`, `.mcpack`, `.mctemplate`, and `.mcaddon`
|
- `.mcpack`
|
||||||
- normalizes archives with either flat contents or a single nested top-level folder
|
- `.mctemplate`
|
||||||
- infers pack type for ambiguous `.mcpack` and `.mcaddon` archives
|
- `.mcaddon`
|
||||||
- `World Manager for Minecraft/Services/MinecraftContentMetadataReader.swift`
|
|
||||||
- shared manifest, icon, display-name, and world metadata parsing
|
Both extensions share the same package inspection and thumbnail rendering code used by the app target where possible.
|
||||||
- `World Manager for Minecraft/QuickLook/MinecraftPackageTypes.swift`
|
|
||||||
- central UTType identifiers and extension definitions
|
## Targets
|
||||||
- `World Manager for Minecraft/QuickLook/MinecraftPackageQuickLookModel.swift`
|
|
||||||
- preview-friendly summary model
|
### Thumbnail Extension
|
||||||
- `World Manager for Minecraft/QuickLook/MinecraftPackageThumbnailRenderer.swift`
|
|
||||||
- branded thumbnail rendering with icon fallback
|
`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`
|
- `MinecraftPackageThumbnailExtension/ThumbnailProvider.swift`
|
||||||
- renders Quick Look thumbnails for supported Minecraft package files
|
- `MinecraftPackagePreviewExtension/Info.plist`
|
||||||
- `MinecraftPackagePreviewExtension/PreviewViewController.swift`
|
- `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`
|
Run:
|
||||||
- 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
|
|
||||||
|
|
||||||
## Verification Notes
|
```sh
|
||||||
|
xcodebuild \
|
||||||
|
-project "World Manager for Minecraft.xcodeproj" \
|
||||||
|
-scheme "World Manager for Minecraft" \
|
||||||
|
-configuration Debug \
|
||||||
|
build
|
||||||
|
```
|
||||||
|
|
||||||
- `xcodebuild ... build` succeeds.
|
The unit tests cover archive inspection behavior in `World Manager for MinecraftTests/World_Manager_for_MinecraftTests.swift`.
|
||||||
- `xcodebuild ... test` should be run before release and whenever the shared archive inspection layer changes.
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user