diff --git a/apps/mobile/src/components/ComposerModelControl.tsx b/apps/mobile/src/components/ComposerModelControl.tsx index b090a24faeb30..cd018ea70a9f3 100644 --- a/apps/mobile/src/components/ComposerModelControl.tsx +++ b/apps/mobile/src/components/ComposerModelControl.tsx @@ -7,7 +7,7 @@ import type { ModelOption } from "../lib/modelOptions"; import { resolveProviderOptionDescriptors } from "../lib/providerOptions"; import { AppText as Text } from "./ui/AppText"; import { ComposerInlineControl } from "./ComposerToolbar"; -import { ProviderIcon, ProviderInstanceIcon } from "./ProviderIcon"; +import { ProviderIcon, ProviderInstanceIcon, providerInstanceNameLabel } from "./ProviderIcon"; export function ComposerModelControl(props: { readonly modelOption: ModelOption | null; @@ -37,6 +37,15 @@ export function ComposerModelControl(props: { : ""; const badge = props.modelOption?.providerBadge; const label = props.modelOption?.label ?? props.selection?.model ?? "Choose model"; + const providerNameLabel = badge + ? providerInstanceNameLabel({ + provider: props.modelOption?.providerDriver, + iconUrl: props.modelOption?.providerIconUrl, + displayName: badge.displayName, + showBadge: badge.showBadge, + }) + : null; + const shortLabel = props.modelOption?.shortName ?? label; return ( ) } - label={props.modelOption?.shortName ?? label} + label={providerNameLabel ?? shortLabel} + labelEllipsizeMode={providerNameLabel ? "middle" : undefined} iconOnly={props.iconOnly} + suffixWidth={providerNameLabel ? 96 : undefined} suffix={ - summary ? ( + providerNameLabel ? ( + + {shortLabel} + {summary ? ` ยท ${summary}` : ""} + + ) : summary ? ( ["name"]; readonly renderIcon?: (size: number) => ReactNode; readonly label: string; + readonly labelEllipsizeMode?: ComponentProps["ellipsizeMode"]; readonly suffix?: ReactNode; + readonly suffixWidth?: number; /** Show only the icon and chevron; the label still names the control for accessibility. */ readonly iconOnly?: boolean; readonly maxWidth?: ViewStyle["maxWidth"]; @@ -94,13 +96,19 @@ export function ComposerInlineControl(props: { props.emphasized || props.selected ? "text-foreground" : "text-foreground-muted", )} numberOfLines={1} + ellipsizeMode={props.labelEllipsizeMode} > {props.label} )} {!props.iconOnly && props.suffix ? ( - {props.suffix} + + {props.suffix} + ) : null} {props.showChevron === false ? null : ( { @@ -764,7 +776,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { : workingLabel) ?? (isUnread ? DONE_STATUS_LABEL : undefined); const recede = shouldRecedeThreadRow({ status, selected }); const isRegeneratingTitle = thread.titleRegeneration != null; - const rowAccessibilityLabel = `${thread.title}${props.hasQueuedMessages ? ", messages queued to send" : ""}${isRegeneratingTitle ? ", regenerating title" : ""}`; + const rowAccessibilityLabel = `${thread.title}${providerNameLabel ? `, ${providerNameLabel}` : ""}${props.hasQueuedMessages ? ", messages queued to send" : ""}${isRegeneratingTitle ? ", regenerating title" : ""}`; const timeLabel = props.timeLabel; const visitThread = useAtomCommand(threadEnvironment.visit, { reportFailure: false }); @@ -1381,6 +1393,21 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { showBadge={providerInstance.showBadge} surfaceColor={rowAppearance.providerIconSurfaceColor} /> + {providerNameLabel ? ( + + {providerNameLabel} + + ) : null} ) : null} @@ -1474,6 +1501,20 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: { > {thread.title} + {providerNameLabel ? ( + + {providerNameLabel} + + ) : null} {props.searchMatch ? (