C.W.K.
Stream
Lesson 03 of 05 · published

Refresh Re-Enumerates

~11 min · refresh, enumeration, selection

Level 0Lost in Finder
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Row 4 is not a file. Row 4 is where a file happened to be drawn last time."

What a Tab Actually Holds

A Waygate tab feels like it "has" a folder open, but look at what it really stores: a LocationReference to the folder, the view mode and sort and filter, back/forward history, and selection restoration hints. Notice what's missing — the list of files. The tab does not own the directory contents. It owns a pointer to a place and instructions for how to render whatever is there right now.

Refresh Is a Fresh Read

So when you refresh, there is nothing to "reload" from memory. Waygate re-enumerates the live location off the main thread and rebuilds the rows from what's actually on disk. If another app added three files and deleted one while you were looking, the refresh shows exactly that. The pane is never more than one enumeration away from the truth, because it never pretended to hold the truth.

Restoring Selection Without Lying

Here's the subtle part. After a refresh, Waygate tries to restore your selection — but only by identity. If the file you had selected is still there (same resource id), it stays selected. If it's gone, the selection quietly drops it rather than selecting whatever slid into that row position. Row index is never identity; display name is never identity. Selecting "row 4" after a refresh would be selecting a stranger.

Refresh re-enumerates; selection restores by identity only. A tab owns a reference and hints, never cached directory truth. Row index and display name are presentation, not identity — so a refresh can never leave you acting on a file that merely inherited a screen position.
Live updates are just cheap refreshes. Waygate can observe a folder for changes and re-enumerate automatically, but the mechanism is the same honest re-read — never a patch that edits cached rows in place. 'Patch the cache' is where phantom rows are born; 're-read the folder' can't produce one.

Code

A tab points at a place; it doesn't cache its contents·swift
struct Tab {
    var location: LocationReference     // WHERE, not WHAT
    var viewMode: ViewMode
    var sort: SortDescriptor
    var filter: String?
    var history: NavigationHistory
    var selectionHints: [ResourceID]    // identities to re-select if still present
    // NOTE: there is no `var files: [File]` here. On purpose.
}

func refresh(_ tab: inout Tab) async throws {
    let rows = try await enumerate(tab.location)          // fresh read, off-main
    let alive = Set(rows.map(\.resourceID))
    // keep only selections whose IDENTITY survived the re-read:
    tab.selectionHints = tab.selectionHints.filter(alive.contains)
    present(rows, reselecting: tab.selectionHints)
}

External links

Exercise

Imagine a file manager that restored selection by row index after a refresh instead of by identity. Walk through a concrete disaster: you select row 4, a background process deletes the file that was above it, you hit refresh, then press Delete. What did you just delete, and why? Then state the one-line rule that prevents it.
Hint
After the deletion, everything shifts up: the file that was row 5 is now row 4. Restore-by-index re-selects row 4 — a different file than you chose — and your Delete lands on it. Restore-by-identity would have seen your original file is gone and selected nothing. Identity, never position.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.