Skip to content
Closed

Dev #6322

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 4 additions & 54 deletions app/components/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,25 @@ import styles from "./auth.module.scss";
import { IconButton } from "./button";
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Path, SAAS_CHAT_URL } from "../constant";
import { Path } from "../constant";
import { useAccessStore } from "../store";
import Locale from "../locales";
import Delete from "../icons/close.svg";
import Arrow from "../icons/arrow.svg";
import Logo from "../icons/logo.svg";
import { useMobileScreen } from "@/app/utils";
import BotIcon from "../icons/bot.svg";
import { getClientConfig } from "../config/client";
import { PasswordInput } from "./ui-lib";
import LeftIcon from "@/app/icons/left.svg";
import { safeLocalStorage } from "@/app/utils";
import {
trackSettingsPageGuideToCPaymentClick,
trackAuthorizationPageButtonToCPaymentClick,
} from "../utils/auth-settings-events";

import clsx from "clsx";

const storage = safeLocalStorage();

export function AuthPage() {
const navigate = useNavigate();
const accessStore = useAccessStore();
const goHome = () => navigate(Path.Home);
const goChat = () => navigate(Path.Chat);
const goSaas = () => {
trackAuthorizationPageButtonToCPaymentClick();
window.location.href = SAAS_CHAT_URL;
};

const resetAccessCode = () => {
accessStore.update((access) => {
access.openaiApiKey = "";
access.accessCode = "";
});
}; // Reset access code to empty string
// Reset access code to empty string

useEffect(() => {
if (getClientConfig()?.isApp) {
Expand Down Expand Up @@ -115,17 +98,10 @@ export function AuthPage() {
type="primary"
onClick={goChat}
/>
<IconButton
text={Locale.Auth.SaasTips}
onClick={() => {
goSaas();
}}
/>
</div>
</div>
);
}

function TopBanner() {
const [isHovered, setIsHovered] = useState(false);
const [isVisible, setIsVisible] = useState(true);
Expand Down Expand Up @@ -159,31 +135,5 @@ function TopBanner() {
if (!isVisible) {
return null;
}
return (
<div
className={styles["top-banner"]}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<div className={clsx(styles["top-banner-inner"], "no-dark")}>
<Logo className={styles["top-banner-logo"]}></Logo>
<span>
{Locale.Auth.TopTips}
<a
href={SAAS_CHAT_URL}
rel="stylesheet"
onClick={() => {
trackSettingsPageGuideToCPaymentClick();
}}
>
{Locale.Settings.Access.SaasStart.ChatNow}
<Arrow style={{ marginLeft: "4px" }} />
</a>
</span>
</div>
{(isHovered || isMobile) && (
<Delete className={styles["top-banner-close"]} onClick={handleClose} />
)}
</div>
);
return null;
}
100 changes: 87 additions & 13 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ import {
copyToClipboard,
getMessageImages,
getMessageTextContent,
getModelSizes,
isDalle3,
isVisionModel,
safeLocalStorage,
getModelSizes,
supportsCustomSize,
useMobileScreen,
selectOrCopy,
showPlugins,
supportsCustomSize,
useMobileScreen,
} from "../utils";

import { uploadImage as uploadImageRemote } from "@/app/utils/chat";
Expand Down Expand Up @@ -535,11 +535,10 @@ export function ChatActions(props: {
const defaultModel = filteredModels.find((m) => m.isDefault);

if (defaultModel) {
const arr = [
return [
defaultModel,
...filteredModels.filter((m) => m !== defaultModel),
];
return arr;
} else {
return filteredModels;
}
Expand All @@ -553,6 +552,7 @@ export function ChatActions(props: {
return model?.displayName ?? "";
}, [models, currentModel, currentProviderName]);
const [showModelSelector, setShowModelSelector] = useState(false);
const [showProviderSelector, setShowProviderSelector] = useState(false);
const [showPluginSelector, setShowPluginSelector] = useState(false);
const [showUploadImage, setShowUploadImage] = useState(false);

Expand Down Expand Up @@ -673,23 +673,97 @@ export function ChatActions(props: {
}}
/>

<ChatAction
onClick={() => setShowProviderSelector(true)}
text={currentProviderName}
icon={<BrainIcon />}
/>

<ChatAction
onClick={() => setShowModelSelector(true)}
text={currentModelName}
icon={<RobotIcon />}
/>

{showProviderSelector && (
<Selector
defaultSelectedValue={currentProviderName}
items={Object.entries(ServiceProvider)
.filter(([_, value]) => {
const accessStore = useAccessStore.getState();
switch (value) {
case ServiceProvider.OpenAI:
return true; // 始终保留OpenAI选项,即使没有配置API密钥
case ServiceProvider.Azure:
return accessStore.isValidAzure();
case ServiceProvider.Google:
return accessStore.isValidGoogle();
case ServiceProvider.Anthropic:
return accessStore.isValidAnthropic();
case ServiceProvider.Baidu:
return accessStore.isValidBaidu();
case ServiceProvider.ByteDance:
return accessStore.isValidByteDance();
case ServiceProvider.Alibaba:
return accessStore.isValidAlibaba();
case ServiceProvider.Tencent:
return accessStore.isValidTencent();
case ServiceProvider.Moonshot:
return accessStore.isValidMoonshot();
case ServiceProvider.Iflytek:
return accessStore.isValidIflytek();
case ServiceProvider.DeepSeek:
return accessStore.isValidDeepSeek();
case ServiceProvider.XAI:
return accessStore.isValidXAI();
case ServiceProvider.ChatGLM:
return accessStore.isValidChatGLM();
case ServiceProvider.SiliconFlow:
return accessStore.isValidSiliconFlow();
case ServiceProvider.Stability:
return true; // 假设不需要验证
default:
return false;
}
})
.map(([name, value]) => ({
title: name,
value: value,
}))}
onClose={() => setShowProviderSelector(false)}
onSelection={(s) => {
if (s.length === 0) return;
const provider = s[0] as ServiceProvider;
chatStore.updateTargetSession(session, (session) => {
session.mask.modelConfig.providerName = provider;
const filteredModels = models.filter(
(m) => m.available && m.provider?.providerName === provider,
);
if (filteredModels.length > 0) {
// 选择新的服务商后,自动选择该服务商下的第一个模型
session.mask.modelConfig.model = filteredModels[0]
.name as ModelType;
session.mask.syncGlobalConfig = false;
}
});
showToast(s[0]);
}}
/>
)}

{showModelSelector && (
<Selector
defaultSelectedValue={`${currentModel}@${currentProviderName}`}
items={models.map((m) => ({
title: `${m.displayName}${
m?.provider?.providerName
? " (" + m?.provider?.providerName + ")"
: ""
}`,
value: `${m.name}@${m?.provider?.providerName}`,
}))}
items={models
.filter(
(m) =>
m.available &&
m.provider?.providerName === currentProviderName,
)
.map((m) => ({
title: m.displayName,
value: `${m.name}@${m?.provider?.providerName}`,
}))}
onClose={() => setShowModelSelector(false)}
onSelection={(s) => {
if (s.length === 0) return;
Expand Down
3 changes: 1 addition & 2 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import dynamic from "next/dynamic";
import { Path, SlotID } from "../constant";
import { ErrorBoundary } from "./error";

import { getISOLang, getLang } from "../locales";
import { getISOLang } from "../locales";

import {
HashRouter as Router,
Expand Down Expand Up @@ -212,7 +212,6 @@ function Screen() {
<div
className={clsx(styles.container, {
[styles["tight-container"]]: shouldTightBorder,
[styles["rtl-screen"]]: getLang() === "ar",
})}
>
{renderContent()}
Expand Down
Loading
Loading