oficina / slides Public

Clone
git clone https://amadan.net/oficina/slides

Plain git — no account needed to clone.

Download

Download this file

1// fixtures/changes.mjs — what a transaction on the slides root means
2// for the editor. Three kinds, and each has one consumer:
3//
4// text a text or notes fragment on a slide changed. Nothing to
5// redraw: y-prosemirror already did, in every bound view.
6// The strip re-fetches that slide's thumbnail.
7// structure a slide's map, a block, its props, region, box or z
8// changed. The stage re-fetches the section when it is the
9// current slide; the strip re-fetches the thumbnail.
10// order the slide list itself changed: a slide added, removed or
11// moved. The strip re-syncs its items.
12//
13// The classification is the walk from an event's target up to the
14// slide map whose parent is the slides array: pass through an Xml type
15// on the way and it was text, otherwise structure; start AT the array
16// and it was the order. One more case since the deck's order became
17// data: a slide's own `order` key (ydoc.mjs, "reading order") is the
18// deck's order, and move_slide writes it rather than moving array
19// entries, so a reorder arrives as a key change on every slide map and
20// not as an event on the array at all. Pure over Yjs types, driven in
21// changes.test.mjs with real observeDeep events.
22import * as Y from 'yjs'
23import { getString } from './ydoc.mjs'
24
25/** {text: [slideId], structure: [slideId], order: bool} for one transaction's deep events. */
26export function classify (events, slides) {
27 const text = new Set()
28 const structure = new Set()
29 let order = false
30 for (const e of events) {
31 let node = e.target
32 if (node === slides) {
33 order = true
34 continue
35 }
36 let isText = false
37 while (node && node.parent !== slides) {
38 if (node instanceof Y.XmlFragment || node instanceof Y.XmlText) isText = true
39 node = node.parent
40 }
41 if (!node) continue
42 const id = getString(node, 'id')
43 if (!id) continue
44 if (isText) { text.add(id); continue }
45 // The event landed on the slide map itself. Its `order` key is the
46 // deck's order; a block's `order` key is not, and reaches here as
47 // an event further down, so keys is null for it.
48 const keys = node === e.target ? e.keysChanged : null
49 if (keys && keys.has('order')) {
50 order = true
51 // A renumbering that touched nothing else has not changed what
52 // the slide looks like, so the strip re-syncs and the stage is
53 // left alone.
54 if (keys.size === 1) continue
55 }
56 structure.add(id)
57 }
58 return { text: [...text], structure: [...structure], order }
59}
60