# Managing Media Import and Indexing with Progress Tracking in Palmier Pro

> Learn how Palmier Pro streamlines media import and indexing with its multi-stage pipeline and real-time progress tracking for efficient project management.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: how-to-guide
- Published: 2026-07-27

---

**Palmier Pro handles media import as a multi-stage, undo-aware pipeline that runs off the main actor, updates a project-wide manifest, and feeds a per-project search index with real-time progress tracking.**

According to the palmier-io/palmier-pro source code, the entire flow is isolated from the main actor to preserve UI responsiveness, and every stage—from Finder drop to search index—is observable and reversible. Understanding how the `EditorViewModel`, `MediaImportScanner`, and `SearchIndexCoordinator` interact is essential for customizing imports or debugging ingestion workflows.

## The Media Import and Indexing Pipeline in Palmier Pro

The import system spans four logical layers: user entry, scanning, plan application, and finalization. Each layer is implemented in dedicated source files under the `Sources/PalmierPro/` directory and communicates through explicit async boundaries that comply with the project’s strict concurrency guidelines.

### User Entry Points

Imports begin in the media panel UI. Tapping the **Import Media** button in [`Sources/PalmierPro/MediaPanel/MediaTab/MediaTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/MediaTab/MediaTab.swift) at line 298 triggers the pipeline. Alternatively, dragging files from Finder into the media panel is handled by `Sources/PalmierPro/MediaPanel/MediaTab/MediaTab+Drag.swift` at line 144. Both paths converge on the same async method:

```swift
await editor.importFinderItems(
    urls,
    into: mediaPanelCurrentFolderId,
    finalize: true
)

```

### Scanning and Building the Import Plan

Before any asset is written, `MediaImportScanner.scan(roots:)` in `Sources/PalmierPro/Editor/ViewModel/EditorViewModel+MediaLibrary.swift` (lines 57-84) evaluates the incoming URLs. It returns a `MediaImportPlan` that catalogs valid folders, files, and rejected items such as unsupported types or non-Lottie files. This stage runs inside a `Task.detached(priority: .userInitiated)` to avoid blocking the main thread.

### Applying the Import Plan with Undo Support

The `applyMediaImportPlan(_:restoringFrom:finalize:)` method in `EditorViewModel+MediaLibrary.swift` (lines 11-68) executes the plan. It creates the folder hierarchy, appends `MediaAsset` objects to the editor’s `mediaAssets` array, updates the `mediaManifest`, and registers a single undo step. Because the undo action captures the pre-import state, an entire batch can be rolled back with one command. If `finalize` is true, the method also invokes `finalizeImportedAsset` for each accepted asset.

### Finalization and Search Indexing

`finalizeImportedAsset(_:batchManifestUpdate:)` at lines 99-143 performs heavy lifting: loading metadata, generating thumbnails and waveforms via `prepareMediaVisuals`, updating the manifest, and enqueueing the asset in the `SearchIndexCoordinator`. The coordinator, defined in [`Sources/PalmierPro/Search/SearchIndexCoordinator.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Search/SearchIndexCoordinator.swift) (lines 3-55), maintains an `indexingActive` flag, an `indexingProgress` value, and a queue of assets awaiting re-indexing.

## Progress Tracking for Media Import and Indexing

Both the import and indexing stages expose observable state so the UI can display accurate feedback without polling the filesystem.

### Import Progress and UI Feedback

While `MediaImportScanner` runs on its detached task, the media panel presents a busy spinner. Once `applyMediaImportPlan` completes, warning toasts—for example, unsupported file alerts surfaced at lines 46-50—are delivered through `mediaPanelToast`. The pipeline respects cancellation via `Task.checkCancellation` at each async boundary.

### Indexing Progress Monitoring

`SearchIndexCoordinator.indexingProgress` is a `Double` calculated as `batchCompleted / batchTotal`. The Settings interface in [`Sources/PalmierPro/Settings/StoragePane.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Settings/StoragePane.swift) (lines 60-89) binds to this property to render a progress bar, and it displays the current disk usage via `indexBytes`. Users can reset the index entirely by triggering the **Clear index** button, which calls:

```swift
await SearchIndexCoordinator.shared.clearIndex()

```

## Programmatic Control Over Media Import and Indexing

Developers can drive the pipeline outside the standard UI. The following examples reproduce the internal flow for batch scripts or custom integrations.

### Importing Finder Items from a Drag-and-Drop

```swift
// Inside a view-model method
await editor.importFinderItems(
    urls,                     // URLs dragged from Finder
    into: mediaPanelCurrentFolderId,
    finalize: true
)

```

### Running a Custom Import Plan

```swift
let roots = [MediaImportScanner.Root(url: sourceURL, parentFolderId: nil)]
let plan  = MediaImportScanner.scan(roots: roots)

// Apply without UI interaction
let summary = editor.applyMediaImportPlan(
    plan,
    restoringFrom: editor.mediaLibraryUndoSnapshot(),
    finalize: true
)

```

### Clearing the Search Index

```swift
// Called from Settings → “Clear index”
await SearchIndexCoordinator.shared.clearIndex()

```

## Key Source Files

- **`Sources/PalmierPro/Editor/ViewModel/EditorViewModel+MediaLibrary.swift`** — Core import scanner, plan builder, undo integration, and finalization logic.
- **[`Sources/PalmierPro/MediaPanel/MediaTab/MediaTab.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/MediaTab/MediaTab.swift)** — UI entry point for the Import button.
- **`Sources/PalmierPro/MediaPanel/MediaTab/MediaTab+Drag.swift`** — Detects clipboard or drag importable media.
- **[`Sources/PalmierPro/Search/SearchIndexCoordinator.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Search/SearchIndexCoordinator.swift)** — Manages the per-project indexing queue and progress reporting.
- **[`Sources/PalmierPro/Settings/StoragePane.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Settings/StoragePane.swift)** — Shows index size, progress, and provides the clear-index command.

## Summary

- Palmier Pro uses a **four-stage pipeline**—entry, scan, apply, finalize—to ingest media off the main actor and keep the UI responsive.
- `MediaImportScanner.scan(roots:)` builds a deterministic `MediaImportPlan` that separates accepted files from rejected items before any disk mutation occurs.
- `applyMediaImportPlan(_:restoringFrom:finalize:)` provides **atomic undo support** by registering a single undo step that reverses the entire batch.
- `finalizeImportedAsset(_:batchManifestUpdate:)` generates visuals and enqueues assets into the `SearchIndexCoordinator`.
- `SearchIndexCoordinator` exposes `indexingProgress` and `indexingActive` to drive UI progress bars, and its state can be reset via `clearIndex()`.

## Frequently Asked Questions

### How does Palmier Pro keep the UI responsive during large media imports?

All scanning work runs in a `Task.detached(priority: .userInitiated)` inside `MediaImportScanner.scan(roots:)`. The actual plan application and finalization also occur off the main actor, so the interface remains fluid even while processing hundreds of files.

### Can an entire import batch be undone?

Yes. `applyMediaImportPlan(_:restoringFrom:finalize:)` in `EditorViewModel+MediaLibrary.swift` registers a single undo step that captures the pre-import `mediaLibraryUndoSnapshot()`. Invoking undo reverts the folder hierarchy, `mediaAssets` array, and `mediaManifest` in one action.

### What happens to unsupported files dropped into the media panel?

The scanner filters them out during the planning phase and records them as rejected items. After the plan is applied, the UI surfaces warnings—such as unsupported type alerts—through the `mediaPanelToast` mechanism between lines 46-50 of the editor extension.

### How is search indexing progress calculated?

`SearchIndexCoordinator` derives `indexingProgress` as the ratio of `batchCompleted` to `batchTotal`. Settings views like [`StoragePane.swift`](https://github.com/palmier-io/palmier-pro/blob/main/StoragePane.swift) observe this `Double` alongside the `indexingActive` flag to render a live progress bar and report `indexBytes` consumed on disk.