Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 2x 2x 2x 2x 279x 34x 34x 34x 34x 279x 279x 2x 8x 8x 8x 8x 8x 8x 2x 2x 2x 2x 2x 2x 127x 127x 127x 2x 30x 30x | /**
* Whether the maps are held on their diagonal (§7.2): Space, the button beside
* the turn, and the palette's *Diagonal lock*.
*
* Locked, a map goes onto its diagonal at the zoom it is at and stays there:
* a drag, a scroll, a pinch and the arrow keys all move it along the line, a
* sideways scroll slides down it, and an Option-drag draws its box on it as
* Option and Shift do (`render/heatmap.ts`). Unlocked, a sideways scroll is the
* columns alone and every gesture goes where the hand does.
*
* One switch for every map on screen rather than one per map, for the reason
* *Refine on zoom*'s is (`ui/refine.ts`): it is a way of reading, and a deck's
* maps move as one (§16.2), so a lead held on its diagonal beside a companion
* that was not would be dragged off it by its own neighbour. It outlives a
* navigation — a step to the next sequence rebuilds the map, and the reader
* stepping along a genome on its diagonal means the next one on it too — and so
* it is kept where *Refine on zoom* is, in `localStorage` and not the hash: a
* link shares what is being looked at, and how the recipient likes to move
* about in it is not that.
*/
const KEY = 'chromosomix:diagonal-lock'
let locked: boolean | null = null
const listeners = new Set<(on: boolean) => void>()
/** Whether the maps are held on their diagonal. Off until the reader asks. */
export function diagonalLocked(): boolean {
if (locked === null) {
try {
locked = window.localStorage.getItem(KEY) === 'on'
} catch {
locked = false
}
}
return locked
}
/** Lock or let go, store it, and tell every mounted map. */
export function setDiagonalLocked(on: boolean): void {
locked = on
try {
window.localStorage.setItem(KEY, on ? 'on' : 'off')
} catch {
/* a browser that refuses storage still honours the choice for this session */
}
for (const listener of [...listeners]) listener(on)
}
export function toggleDiagonalLock(): boolean {
const next = !diagonalLocked()
setDiagonalLocked(next)
return next
}
/** Hear the lock taken and released; returns the unsubscribe. */
export function subscribeDiagonalLock(listener: (on: boolean) => void): () => void {
listeners.add(listener)
return () => listeners.delete(listener)
}
/** Forget the stored choice, for a test that wants a reader who never pressed it. */
export function resetDiagonalLock(): void {
locked = null
}
|