Skip to main content

Module groups

Module groups 

Expand description

Where a version’s name lives: in the document, with the changes it names.

A name that lived in the widget would vanish on close, and one beside the document would never reach a collaborator. So a name is written into the same CRDT as the content it describes — one record at the document root per named range, keyed by the range it covers:

ROOT
  "tilo:group:<hex of the range's first change>"   <- the key IS the range
     label : "Intro rewrite"
     end   : "<hex of the range's last change>"   (absent while open)
     by    : "<actor hex of whoever wrote the name>"
     at    : <unix millis>

The key is the range’s first change, not minted per writer, so two people naming the same run collide on one map key and automerge’s conflict rule resolves it identically on every peer. Records sit at the root rather than under one container map for the same reason at a coarser grain: a container created independently by two peers naming different ranges would have one discarded whole, silently losing a name.

Naming a version is a change like any other, but deliberately gets no row of its own in the history surfaces — see is_group_marker.

Structs§

DisplayedSession
One work session beside a seam, as the person saw it: its named record, or None while it is still an automatic projection with these bounds and title.

Constants§

GENERATED_BY
The by of a name a model wrote, in place of a person’s actor hex. A generated name is the document’s guess at what a run of changes was: it is replaced by anyone who names the same range, and it is never shown as somebody’s words (NamedRange::named_by stays empty for it).
GROUPS_KEY
Namespaced so it cannot collide with an app’s own schema: tilo-doc uses content / comments / props, and the shell’s workspace document uses workspaces / active.
MAX_LABEL_LEN
A version name is a label, not a paragraph; past this it stops fitting anywhere it is rendered and starts being a way to make another user’s timeline unreadable.

Functions§

apply_name_request
Write what a GroupNameRequest asks for: name its range, or, with an empty label, remove the name it replaces. A range named again from another first change drops the record it replaces, so one run of changes carries one name. false when there was nothing to write. The transaction is left open for the host to commit.
clear_name
Remove a name. The changes it covered stay; only the band goes.
close_range
Close an open range at end. false when no such record exists.
is_group_marker
True when every patch in patches lands inside the named-range map — used by the producer to keep naming out of the row list. An empty patch set is not a marker: a change that did nothing visible is still a change, and hiding it would be incorrect behaviour.
materialize_and_move_boundary
Correct a seam even when one or both work sessions are still automatic projections. Missing records are materialized with the titles and bounds the person saw, then the bordering action is moved in the same document transaction. The atomic history entries themselves are never rewritten.
merge_named_ranges
Merge named bands into one caller-resolved range. Every old record must exist before anything is changed, so a stale UI cannot partially merge a set that a collaborator has already edited.
move_named_boundary
Move the boundary between two named bands while preserving both labels. As with split, the caller resolves the two sides from its displayed causal order and sends exact ids.
name_is_generated
Whether the name at record_id was written by a model rather than a person. A record this device cannot read counts as a person’s: never overwrite what another writer may have said.
name_range
Names the run of changes from start to end, or opens an unbounded run when end is None. Returns the record id (also the document key). The transaction is left open — the host commits, so the naming lands stamped and attributed like any other edit.
name_range_by
name_range, with the by written into the record: a person’s actor hex, or GENERATED_BY for a name a model wrote.
read_named_ranges
Records that do not parse (a corrupted key, a missing label) are skipped rather than guessed at — a band in the wrong place is worse than no band.
split_named_range
Split one named band into two adjacent named bands in the current transaction. The caller supplies both boundary ids because a CRDT history is not inherently linear at concurrent branches; guessing adjacency here would make the operation non-deterministic across peers.