All files / src/ui modCodes.ts

100% Statements 17/17
77.77% Branches 7/9
100% Functions 3/3
100% Lines 17/17

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                                2x 2x     2x 2x 2x 2x 2x 2x 2x 2x     2x 8x 8x     2x 3x 3x 3x  
/**
 * Which base-modification codes a BAM's rows have met, for the settings card.
 *
 * The card is built from the store and a row's codes are a fact about the
 * *reads*, which only the lanes hold: a pile's calls (`ReadPile.mods`) and a
 * depth row's fraction (`TrackSampleSet.mods`) each name the codes their
 * window carried. The lanes report them here as they draw, and the picker
 * listens — so it offers the modifications this file actually has rather than
 * the spec's whole table, and grows as the reader pans onto a read with
 * another one.
 *
 * Kept per entry and only ever added to: a code met once is still in the file
 * when the view moves off it, and a select whose options came and went under
 * the reader's pan would be a control that changes by itself.
 */
 
const seen = new Map<string, string[]>()
const listeners = new Set<(entry: string) => void>()
 
/** Record codes a lane met; tells the pickers only when something is new. */
export function noteModCodes(entry: string, codes: readonly string[]): void {
  if (codes.length === 0) return
  const held = seen.get(entry) ?? []
  const fresh = codes.filter((code) => !held.includes(code))
  if (fresh.length === 0) return
  seen.set(entry, [...held, ...fresh])
  for (const listener of listeners) listener(entry)
}
 
/** Every code met on this entry so far, in the order they were met. */
export function modCodesOf(entry: string): string[] {
  return seen.get(entry) ?? []
}
 
/** Be told when an entry meets a new code. Returns the unsubscribe. */
export function onModCodes(listener: (entry: string) => void): () => void {
  listeners.add(listener)
  return () => listeners.delete(listener)
}