//! The Askama entry point for the described media picker. //! //! Shape 4 of the conversion plan (wiki `mnw-shape-conversion-plans`), step 1. //! [`Act::fills`](quasi_router::Act::fills) is what expresses the deposit, so //! `static/media-picker.js` is gone. //! //! # What a card says now //! //! `Act::new(filename, Action::local()).filling("body", reference)`. The //! destination is a field name and never a caret: a webview inserts at the //! selection, and where inside a box a value lands was never the description's //! to say. The action is [`Destination::Local`](quasi_router::Destination), so //! a pick makes no request at all — the old picker made none either, and the //! two round trips this shape does cost are the open and the dismiss. //! //! # Three defects the shipped picker has, which this does not //! //! Found reading `media-picker.js:83-84` against `MediaFileResponse` //! (`routes/storage/media.rs:66`), and none of them is a conversion decision — //! the described version cannot have any of the three, because the value is //! held once on the server instead of being spelled again in a browser. //! //! 1. **Every card is unlabelled.** The JSON field is `filename`; the script //! reads `f.file_name`, which is `undefined`. So `label.textContent` and //! `img.alt` are both the empty string on every tile. //! 2. **The name filter matches nothing.** `card.dataset.name` comes from the //! same `undefined`, so typing one character hides the entire library. //! 3. **The inserted reference is wrapped twice.** `markdown_ref` is already //! `![](folder/file.png)` (`media.rs:109-113`) and `_mediaPickerSelect` //! inserts `'![](' + ref + ')'`, so what lands in the box is //! `![](![](folder/file.png))`. //! //! Filed as its own record rather than only fixed here, because (3) means the //! documents people have already written with this button carry broken image //! references that no redeploy repairs. //! //! # Why only the grid is replaced when a filter moves //! //! The plan said the filter controls carry `changes` and the server re-renders //! the grid as a fragment. It said the fragment is aimed at the modal; it is //! aimed at [`GRID`] instead, one region further in. Replacing the modal would //! replace the box being typed into, which takes the caret with it on every //! keystroke. //! //! The name box also asks through a [`Consult`] rather than through `changes`, //! which is the plan's one other deviation and is the same call //! [`crate::quasi::discover_typeahead`] made: `changes` fires per keystroke and //! a media library is a Postgres round trip, where a consult carries the wait //! that makes it one question per pause. The folder select keeps `changes`, //! because a select settles rather than being typed into. //! //! # The destination has to be unique in the document, and that is new //! //! [`Act::fills`] names a [`Field::name`], and a name identifies a field within //! one description. `Filling::id_prefix` exists because that stops being true //! when a document holds two copies of one form, and //! [`crate::quasi::rich_field`] leans on it: five editors, all named `body`, //! told apart by their ids. //! //! So an editor a picker can write into has to be the only `body` in its //! document. Both surfaces that had a working button already are: //! `dashboard-blog-editor.html` holds `post-body` alone, and //! `item_details.html` holds `text-body` alone under that name. The two section //! editors on that same page were raw `