All files / modes/basic/src modeCustomization.ts

51.72% Statements 15/29
38.46% Branches 5/13
57.14% Functions 4/7
55.55% Lines 15/27

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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102                                1171x     1171x                       178x   178x 178x 2084x                         178x     178x 178x 637x     637x                                           178x 178x 178x                                     178x    
/**
 * Helpers for applying a mode's toolbar / tool-group composition.
 *
 * The composition values (`toolbarButtons`, `toolbarSections`,
 * `toolGroupAdditions`) are ordinary customizations resolved through the
 * customization service. A mode lists the capability packs it uses with
 * `{ $reference: '<name>' }` markers; the service expands those at read time
 * (packs that are arrays are flattened into the surrounding list), and a site
 * `?customization=` module extends or replaces them with immutability-helper
 * commands (`$push` another `{ $reference }`, `$set` a hard-coded value, ...).
 * By the time these helpers run, the values passed in are already fully
 * resolved — so they only need to shape/register them.
 */
 
/** Normalizes a value to an array (wrapping a single object, dropping nullish). */
function toArray(value: unknown): any[] {
  Iif (value === undefined || value === null) {
    return [];
  }
  return Array.isArray(value) ? value : [value];
}
 
/**
 * Registers a mode's toolbar from its resolved composition.
 *
 * `toolbarButtons` is a flat list of button definitions registered with the
 * toolbar service.  `toolbarSections` is one or more
 * `{ sectionKey: buttonIds[] }` objects shallow-merged in order (later values
 * win per section) and applied with `updateSection`.
 */
export function registerModeToolbar({ toolbarService }, { toolbarButtons, toolbarSections }): void {
  toolbarService.register(toArray(toolbarButtons));
 
  const sections: Record<string, string[]> = Object.assign({}, ...toArray(toolbarSections));
  for (const [key, section] of Object.entries(sections)) {
    toolbarService.updateSection(key, section);
  }
}
 
/**
 * Adds extra tools to the tool groups a mode has already created.
 *
 * `toolGroupAdditions` is a resolved object mapping a tool group id to a list
 * of tool blocks (each a `{ active/passive/enabled/disabled }` object). Tool
 * groups the mode did not create are skipped, so a single additions object can
 * be shared between modes with different tool group sets.
 */
export function applyToolGroupAdditions({ toolGroupService }, toolGroupAdditions): void {
  Iif (!toolGroupAdditions) {
    return;
  }
  for (const additions of toArray(toolGroupAdditions)) {
    for (const [toolGroupId, toolBlocks] of Object.entries(additions)) {
      Iif (!toolGroupService.getToolGroup(toolGroupId)) {
        continue;
      }
      for (const tools of toArray(toolBlocks)) {
        toolGroupService.addToolsToToolGroup(toolGroupId, tools);
      }
    }
  }
}
 
/**
 * Wires up a mode's ActivatePanel event triggers from data.
 *
 * `activatePanelTriggers` is a list of
 * `{ panelId, sourceServiceName, sourceEvents, forceActive? }` entries;
 * `sourceEvents` names are looked up in the source service's `EVENTS` map
 * (falling back to the raw value) so the whole entry is JSON-serializable and
 * can be supplied by a `?customization=` module or an extending mode.
 *
 * Returns the unsubscribe functions for the subscriptions created.
 */
export function addActivatePanelTriggers(
  { servicesManager },
  activatePanelTriggers
): (() => void)[] {
  const { panelService } = servicesManager.services;
  const unsubscriptions: (() => void)[] = [];
  for (const trigger of activatePanelTriggers ?? []) {
    const { panelId, sourceServiceName, sourceEvents, forceActive = true } = trigger;
    const sourcePubSubService = servicesManager.services[sourceServiceName];
    Iif (!sourcePubSubService) {
      console.warn(`addActivatePanelTriggers: no service registered for "${sourceServiceName}"`);
      continue;
    }
    const subscriptions = panelService.addActivatePanelTriggers(
      panelId,
      [
        {
          sourcePubSubService,
          sourceEvents: sourceEvents.map(name => sourcePubSubService.EVENTS?.[name] ?? name),
        },
      ],
      forceActive
    );
    unsubscriptions.push(...subscriptions.map(subscription => () => subscription.unsubscribe()));
  }
  return unsubscriptions;
}