queueItemName.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. /**
  2. * Display name for a queue item, wherever one is shown.
  3. *
  4. * Every surface used to inline the same fallback chain, which produced
  5. * `File #null` for a cross-model item (#671): those deliberately hold neither
  6. * `archive_id` nor `library_file_id` until dispatch resolves a candidate, so
  7. * that the ON DELETE CASCADE on `library_file_id` can't destroy the whole job
  8. * when one alternative is deleted. Nothing to point at is the design working;
  9. * the label just had nowhere to look.
  10. */
  11. interface NameableQueueItem {
  12. archive_name?: string | null;
  13. library_file_name?: string | null;
  14. archive_id?: number | null;
  15. library_file_id?: number | null;
  16. variants?: Array<{ filename: string }>;
  17. }
  18. /**
  19. * @param item the queue item to name
  20. * @param moreLabel formats the "+N more" suffix for a cross-model item; pass
  21. * the caller's `t` binding so the count stays translated.
  22. * Omitted in compact surfaces that only have room for a name.
  23. */
  24. export function queueItemDisplayName(
  25. item: NameableQueueItem,
  26. moreLabel?: (count: number) => string,
  27. ): string {
  28. if (item.archive_name) return item.archive_name;
  29. if (item.library_file_name) return item.library_file_name;
  30. // Cross-model item: name it after the candidate the user put first — the one
  31. // the scheduler will try first — and say how many others are behind it.
  32. const variants = item.variants ?? [];
  33. if (variants.length > 0) {
  34. const first = variants[0].filename;
  35. const others = variants.length - 1;
  36. if (others > 0 && moreLabel) return `${first} ${moreLabel(others)}`;
  37. return first;
  38. }
  39. return `File #${item.archive_id ?? item.library_file_id}`;
  40. }