| ... | ... | @@ -96,6 +96,21 @@ export function groupModelsForDisplay< |
| 96 | 96 | ]; |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | export function nextHiddenModelsForBulkToggle( |
| 100 | models: ReadonlyArray<Pick<ServerProviderModel, "slug" | "isCustom">>, |
| 101 | hiddenModels: ReadonlyArray<string>, |
| 102 | ): string[] { |
| 103 | const builtInSlugs = models.filter((model) => !model.isCustom).map((model) => model.slug); |
| 104 | const builtInSlugSet = new Set(builtInSlugs); |
| 105 | const allBuiltInModelsHidden = builtInSlugs.every((slug) => hiddenModels.includes(slug)); |
| 106 | |
| 107 | if (allBuiltInModelsHidden) { |
| 108 | return hiddenModels.filter((slug) => !builtInSlugSet.has(slug)); |
| 109 | } |
| 110 | |
| 111 | return [...new Set([...hiddenModels, ...builtInSlugs])]; |
| 112 | } |
| 113 | |
| 99 | 114 | interface ProviderModelsSectionProps { |
| 100 | 115 | /** Identifier used to namespace input ids within the DOM. */ |
| 101 | 116 | readonly instanceId: ProviderInstanceId; |
| ... | ... | @@ -181,6 +196,8 @@ export function ProviderModelsSection({ |
| 181 | 196 | (model) => !model.isCustom && hiddenModelSet.has(model.slug), |
| 182 | 197 | ).length; |
| 183 | 198 | const builtInModels = useMemo(() => models.filter((model) => !model.isCustom), [models]); |
| 199 | const allBuiltInModelsHidden = |
| 200 | builtInModels.length > 0 && builtInModels.every((model) => hiddenModelSet.has(model.slug)); |
| 184 | 201 | const showFilter = models.length > FILTER_THRESHOLD; |
| 185 | 202 | const normalizedFilter = filter.trim().toLowerCase(); |
| 186 | 203 | const isFiltering = showFilter && normalizedFilter.length > 0; |
| ... | ... | @@ -502,11 +519,27 @@ export function ProviderModelsSection({ |
| 502 | 519 | aria-label="Filter models" |
| 503 | 520 | /> |
| 504 | 521 | ) : null} |
| 505 | | <span className="text-xs text-muted-foreground"> |
| 506 | | {models.length} model{models.length === 1 ? "" : "s"} |
| 507 | | {favoriteCount > 0 ? ` · ${favoriteCount} favorite${favoriteCount === 1 ? "" : "s"}` : ""} |
| 508 | | {hiddenCount > 0 ? ` · ${hiddenCount} hidden` : ""} |
| 509 | | </span> |
| 522 | <div className="flex items-center gap-2"> |
| 523 | {builtInModels.length > 0 ? ( |
| 524 | <Button |
| 525 | type="button" |
| 526 | size="xs" |
| 527 | variant="ghost-muted" |
| 528 | onClick={() => |
| 529 | onHiddenModelsChange(nextHiddenModelsForBulkToggle(models, hiddenModels)) |
| 530 | } |
| 531 | > |
| 532 | {allBuiltInModelsHidden ? "Enable all" : "Disable all"} |
| 533 | </Button> |
| 534 | ) : null} |
| 535 | <span className="text-xs text-muted-foreground"> |
| 536 | {models.length} model{models.length === 1 ? "" : "s"} |
| 537 | {favoriteCount > 0 |
| 538 | ? ` · ${favoriteCount} favorite${favoriteCount === 1 ? "" : "s"}` |
| 539 | : ""} |
| 540 | {hiddenCount > 0 ? ` · ${hiddenCount} hidden` : ""} |
| 541 | </span> |
| 542 | </div> |
| 510 | 543 | </div> |
| 511 | 544 | <div |
| 512 | 545 | ref={listRef} |