fix(chat): split image and video model lists by mode
This commit is contained in:
parent
abadcdaa18
commit
eec91f3c6f
@ -52,6 +52,14 @@ const VIDEO_PROVIDER_TYPES = new Set([
|
||||
"fal-video",
|
||||
]);
|
||||
|
||||
function isVideoProviderType(providerType?: string | null) {
|
||||
return VIDEO_PROVIDER_TYPES.has(String(providerType || ""));
|
||||
}
|
||||
|
||||
function isImageGenerationModel(model: DynamicModel) {
|
||||
return model.supportsImageGen === true && !isVideoProviderType(model.providerType);
|
||||
}
|
||||
|
||||
function isNanoBananaProModel(model: { displayName?: string | null; modelId?: string | null }) {
|
||||
const displayName = String(model.displayName || "").toLowerCase();
|
||||
const modelId = String(model.modelId || "").toLowerCase();
|
||||
@ -237,21 +245,20 @@ function PureMultimodalInput({
|
||||
const models = modelCatalog?.models || [];
|
||||
const nanoBananaImage = models.find(
|
||||
(model) =>
|
||||
model.supportsImageGen &&
|
||||
!VIDEO_PROVIDER_TYPES.has(model.providerType || "") &&
|
||||
isImageGenerationModel(model) &&
|
||||
isNanoBananaProModel(model)
|
||||
);
|
||||
const imageMain = models.find(
|
||||
(model) => model.supportsImageGen && !VIDEO_PROVIDER_TYPES.has(model.providerType || "") && !model.isSubModel
|
||||
(model) => isImageGenerationModel(model) && !model.isSubModel
|
||||
);
|
||||
const imageFallback = models.find(
|
||||
(model) => model.supportsImageGen && !VIDEO_PROVIDER_TYPES.has(model.providerType || "")
|
||||
(model) => isImageGenerationModel(model)
|
||||
);
|
||||
const videoMain = models.find(
|
||||
(model) => VIDEO_PROVIDER_TYPES.has(model.providerType || "") && !model.isSubModel
|
||||
(model) => isVideoProviderType(model.providerType) && !model.isSubModel
|
||||
);
|
||||
const videoFallback = models.find((model) =>
|
||||
VIDEO_PROVIDER_TYPES.has(model.providerType || "")
|
||||
isVideoProviderType(model.providerType)
|
||||
);
|
||||
return {
|
||||
image: nanoBananaImage || imageMain || imageFallback || null,
|
||||
@ -260,14 +267,14 @@ function PureMultimodalInput({
|
||||
}, [modelCatalog?.models]);
|
||||
|
||||
const activeQuickMode = useMemo<"image" | "video" | null>(() => {
|
||||
if (isVideoModel || VIDEO_PROVIDER_TYPES.has(currentSelectedModel?.providerType || "")) {
|
||||
if (isVideoModel || isVideoProviderType(currentSelectedModel?.providerType)) {
|
||||
return "video";
|
||||
}
|
||||
if (isImageModel || currentSelectedModel?.supportsImageGen) {
|
||||
if (isImageModel || (currentSelectedModel && isImageGenerationModel(currentSelectedModel))) {
|
||||
return "image";
|
||||
}
|
||||
return null;
|
||||
}, [currentSelectedModel?.providerType, currentSelectedModel?.supportsImageGen, isImageModel, isVideoModel]);
|
||||
}, [currentSelectedModel, isImageModel, isVideoModel]);
|
||||
|
||||
const switchComposerMode = useCallback(
|
||||
(targetMode: "image" | "video") => {
|
||||
@ -1255,6 +1262,7 @@ function PureMultimodalInput({
|
||||
selectedModelId={selectedModelId}
|
||||
attachments={attachments}
|
||||
avatarOnly={true}
|
||||
modeFilter="video"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
@ -1269,6 +1277,7 @@ function PureMultimodalInput({
|
||||
onModelChange={onModelChange}
|
||||
selectedModelId={selectedModelId}
|
||||
attachments={attachments}
|
||||
modeFilter="image"
|
||||
/>
|
||||
) : null}
|
||||
{isImageModel && onImageParamsChange && (
|
||||
@ -1417,12 +1426,14 @@ function PureModelSelectorCompact({
|
||||
attachments,
|
||||
avatarOnly = false,
|
||||
readOnly = false,
|
||||
modeFilter = "all",
|
||||
}: {
|
||||
selectedModelId: string;
|
||||
onModelChange?: (modelId: string) => void;
|
||||
attachments: Attachment[];
|
||||
avatarOnly?: boolean;
|
||||
readOnly?: boolean;
|
||||
modeFilter?: "all" | "image" | "video";
|
||||
}) {
|
||||
const [optimisticModelId, setOptimisticModelId] = useState(selectedModelId);
|
||||
|
||||
@ -1496,9 +1507,20 @@ function PureModelSelectorCompact({
|
||||
providerName: "System",
|
||||
};
|
||||
|
||||
const modeFilteredModels = useMemo(() => {
|
||||
if (modeFilter === "video") {
|
||||
return dynamicModels.filter((model) => isVideoProviderType(model.providerType));
|
||||
}
|
||||
if (modeFilter === "image") {
|
||||
return dynamicModels.filter((model) => isImageGenerationModel(model));
|
||||
}
|
||||
return dynamicModels;
|
||||
}, [dynamicModels, modeFilter]);
|
||||
|
||||
// 合并模型列表(根据设置决定是否包含自动模型)
|
||||
const showAutoModel = siteSettings?.showAutoModel ?? true;
|
||||
const displayModels = showAutoModel ? [autoModel, ...dynamicModels] : dynamicModels;
|
||||
const canShowAutoModel = showAutoModel && modeFilter === "all";
|
||||
const displayModels = canShowAutoModel ? [autoModel, ...modeFilteredModels] : modeFilteredModels;
|
||||
|
||||
useEffect(() => {
|
||||
setOptimisticModelId(selectedModelId);
|
||||
@ -1510,10 +1532,12 @@ function PureModelSelectorCompact({
|
||||
const currentExists = displayModels.some((m) => m.id === selectedModelId);
|
||||
if (currentExists) return;
|
||||
|
||||
const fallbackImageModel =
|
||||
modeFilteredModels.find((model) => isNanoBananaProModel(model)) ||
|
||||
modeFilteredModels.find((model) => model.isDefault) ||
|
||||
modeFilteredModels[0];
|
||||
const fallbackModelId =
|
||||
dynamicModels.find((m) => m.isDefault)?.id ??
|
||||
dynamicModels[0]?.id ??
|
||||
(showAutoModel ? "auto" : "");
|
||||
fallbackImageModel?.id ?? (canShowAutoModel ? "auto" : "");
|
||||
|
||||
if (!fallbackModelId) return;
|
||||
|
||||
@ -1522,7 +1546,7 @@ function PureModelSelectorCompact({
|
||||
startTransition(() => {
|
||||
saveChatModelAsCookie(fallbackModelId);
|
||||
});
|
||||
}, [displayModels, dynamicModels, onModelChange, selectedModelId, showAutoModel]);
|
||||
}, [canShowAutoModel, displayModels, modeFilteredModels, onModelChange, selectedModelId]);
|
||||
|
||||
// 自动选择模型的逻辑 - 必须在所有条件 return 之前定义
|
||||
const selectBestModel = useCallback(() => {
|
||||
@ -1760,6 +1784,9 @@ const ModelSelectorCompact = memo(
|
||||
if (prevProps.readOnly !== nextProps.readOnly) {
|
||||
return false;
|
||||
}
|
||||
if (prevProps.modeFilter !== nextProps.modeFilter) {
|
||||
return false;
|
||||
}
|
||||
if (!equal(prevProps.attachments, nextProps.attachments)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user