Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule fs.module·originates fromworld 07158574-5…

controller

The state half of the generic Explorer. The `Z.fs.*` builders are stateless (data in, widgets out); this controller owns the VFS-backed navigation state and the callback routing that drives them, so both the Files panel and the save/load dialog reuse one model and one router.

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

controller

The state half of the generic Explorer. The Z.fs.* builders are stateless (data in, widgets out); this controller owns the VFS-backed navigation state and the callback routing that drives them, so both the Files panel and the save/load dialog reuse one model and one router.

It operates on a caller-owned slot table (so two Explorers — e.g. the panel and a dialog — keep independent state) and a caller-chosen callback prefix (so their widgets' callbacks don't collide). The controller caches directory listings, tracks the current directory, the expanded folder set, the selected path, and a file preview.

API

  • M.init(slot, opts?) -> slot — idempotently seed a controller state slot. opts.root defaults to /zero/.
  • M.model(slot) — build the render model the Z.fs.explorer / Z.fs.dialog builders consume: { root, currentDir, breadcrumbPath, treeRoots, listEntries, selectedPath, expanded, preview }.
  • M.handle(slot, prefix, callbackId, data?) -> boolean — route an Explorer callback against this slot; returns true when handled.
  • M.invalidate(slot, pathPrefix?) — drop cached listings under pathPrefix (or all when nil) so fresh writes show.
  • M.readPreview(path) -> (text|nil, note, size) — read a file preview; refuses binary, truncates large text.
  • M.confirmTarget(slot, mode, filename) -> path|nil — resolve the absolute target a dialog confirm should act on. In "save" mode it's currentDir .. filename (nil if filename is empty); in "open" mode it's the selected file (nil if nothing or a folder is selected).

Callback grammar

All callbacks carry the absolute path verbatim:

  • <prefix>-nav-<path> — breadcrumb segment
  • <prefix>-tree-select-<path> — tree row
  • <prefix>-tree-toggle-<path> — tree chevron
  • <prefix>-list-<d|f>-<path> — details-list row (d = dir, f = file)
  • <prefix>-up — parent directory
  • <prefix>-refresh — drop cache for the visible subtree

Usage

local fsc = require("modules.zui.widget.fs.controller")
fsc.init(state.files, { root = "/zero/" })
local model = fsc.model(state.files)
local widget = Z.fs.explorer(model, { prefix = "files" })
-- in onCallback:
if fsc.handle(state.files, "files", callbackId, data) then end

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

ZuiFsController Module The state half of the generic Explorer. The `Z.fs.*` builders are stateless (data in → widgets out); this controller owns the VFS-backed navigation state and the callback handling that drives them, so both the Files panel and the save/load dialog reuse one model + one router instead of each re-implementing directory walking. It operates on a caller-owned `slot` table (so two Explorers — e.g. the panel and a dialog — keep independent state) and a caller-chosen callback `prefix` (so their widgets' callbacks don't collide). local fsc = require("modules.deprecated.zui.widget.fs.controller") fsc.init(state.files, { root = "/zero/" }) local model = fsc.model(state.files) local widget = Z.fs.explorer(model, { prefix = "files" }) -- in onCallback: if fsc.handle(state.files, "files", callbackId, data) then ... end Callback grammar (all carry the absolute path verbatim — a trailing path can't break a fixed-prefix match, unlike a Lua pattern): <prefix>-nav-<path> breadcrumb segment <prefix>-tree-select-<path> tree row <prefix>-tree-toggle-<path> tree chevron <prefix>-list-<d|f>-<path> details-list row (d=dir, f=file) <prefix>-up parent directory <prefix>-refresh drop cache for the visible subtree

ensureTrailingSlash(path: ?) → void

argtypedescription
path?

joinPath(dir: ?, name: ?) → void

argtypedescription
dir?
name?

parentDir(path: ?) → void

argtypedescription
path?

baseName(path: ?) → void

argtypedescription
path?

isDirEntry(entry: ?) → void

argtypedescription
entry?

entryName(entry: ?) → void

argtypedescription
entry?

listDir(slot: ?, path: ?) → void

argtypedescription
slot?
path?

buildNodeTree(slot: ?, rootPath: ?) → void

Recursive node tree from `rootPath`, listing only expanded folders.

argtypedescription
slot?
rootPath?

walk(path: ?) → void

argtypedescription
path?

dirEntries(slot: ?, dir: ?) → void

Current-directory entries, each carrying its absolute path.

argtypedescription
slot?
dir?

invalidate(slot: ?, prefix: ?) → void

argtypedescription
slot?
prefix?

fileExt(name: ?) → void

argtypedescription
name?

readPreview(path: ?) →

Read a preview for a file: refuses binary, truncates large text, returns (text, note, size).

argtypedescription
path?Absolute VFS path.

init(slot: ?, opts: ?) →

Seed (idempotently) a controller state slot.

argtypedescription
slot?Caller-owned table the controller stores its state in.
opts?Optional `{ root = "/zero/" }`.

model(slot: ?) →

Build the render model the `Z.fs.explorer` / `Z.fs.dialog` builders consume.

argtypedescription
slot?An initialised controller slot.

navTo(slot: ?, dir: ?) → void

Internal: navigate into a folder (sets current dir + expands it in the tree).

argtypedescription
slot?
dir?

selectFile(slot: ?, path: ?) → void

Internal: select a file (loads its preview).

argtypedescription
slot?
path?

after(cb: ?, marker: ?) → void

Internal: if `cb` starts with `marker`, return the remainder, else nil.

argtypedescription
cb?
marker?

handle(slot: ?, prefix: ?, callbackId: ?, _data: ?) →

Route an Explorer callback against this slot. Returns true when handled.

argtypedescription
slot?An initialised controller slot.
prefix?The callback prefix the matching `Z.fs.explorer`/`dialog` was built with.
callbackId?The widget callback id.
_data?Optional payload (unused; reserved).

invalidate(slot: ?, pathPrefix: ?) → void

Drop cached listings under `prefix` (or all when nil) so fresh writes show.

argtypedescription
slot?An initialised controller slot.
pathPrefix?Absolute-path prefix to invalidate, or nil for everything.

confirmTarget(slot: ?, mode: ?, filename: ?) →

Resolve the absolute target path a dialog confirm should act on. In "save" mode it's `currentDir .. filename` (nil if filename is empty); in "open" mode it's the selected file (nil if nothing or a folder is selected).

argtypedescription
slot?An initialised controller slot.
mode?"save" | "open".
filename?The filename field value (save mode).

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · modules/deprecated/zui.module/widget.module/fs.module/controller.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.