revert: restore app/appType param compatibility and revert segmented-thumb pointer-events change
- Restore backend commands to accept app_type/app/appType with priority app_type
- Frontend invoke() now passes both { app_type, app } again
- Revert CSS change that set pointer-events: none on segmented-thumb
- Keep minor fix: open_config_folder signature uses handle + respects both names
Note: warnings for non_snake_case (appType) are expected for compatibility.
This commit is contained in:
@@ -455,13 +455,13 @@ pub async fn get_claude_code_config_path() -> Result<String, String> {
|
|||||||
/// 兼容两种参数:`app_type`(推荐)或 `app`(字符串)
|
/// 兼容两种参数:`app_type`(推荐)或 `app`(字符串)
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn open_config_folder(
|
pub async fn open_config_folder(
|
||||||
app: tauri::AppHandle,
|
handle: tauri::AppHandle,
|
||||||
app_type: Option<AppType>,
|
app_type: Option<AppType>,
|
||||||
app_str: Option<String>,
|
app: Option<String>,
|
||||||
appType: Option<String>,
|
appType: Option<String>,
|
||||||
) -> Result<bool, String> {
|
) -> Result<bool, String> {
|
||||||
let app_type = app_type
|
let app_type = app_type
|
||||||
.or_else(|| app_str.as_deref().map(|s| s.into()))
|
.or_else(|| app.as_deref().map(|s| s.into()))
|
||||||
.or_else(|| appType.as_deref().map(|s| s.into()))
|
.or_else(|| appType.as_deref().map(|s| s.into()))
|
||||||
.unwrap_or(AppType::Claude);
|
.unwrap_or(AppType::Claude);
|
||||||
|
|
||||||
@@ -476,7 +476,7 @@ pub async fn open_config_folder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用 opener 插件打开文件夹
|
// 使用 opener 插件打开文件夹
|
||||||
app.opener()
|
handle.opener()
|
||||||
.open_path(config_dir.to_string_lossy().to_string(), None::<String>)
|
.open_path(config_dir.to_string_lossy().to_string(), None::<String>)
|
||||||
.map_err(|e| format!("打开文件夹失败: {}", e))?;
|
.map_err(|e| format!("打开文件夹失败: {}", e))?;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,9 @@
|
|||||||
background: var(--seg-thumb);
|
background: var(--seg-thumb);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
||||||
transition: transform 220ms ease, width 220ms ease;
|
transition:
|
||||||
|
transform 220ms ease,
|
||||||
|
width 220ms ease;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/App.tsx
10
src/App.tsx
@@ -182,16 +182,14 @@ function App() {
|
|||||||
<header className="app-header">
|
<header className="app-header">
|
||||||
<h1>{activeApp === "claude" ? "Claude Code" : "Codex"} 供应商切换器</h1>
|
<h1>{activeApp === "claude" ? "Claude Code" : "Codex"} 供应商切换器</h1>
|
||||||
<div className="app-tabs">
|
<div className="app-tabs">
|
||||||
<div
|
<div className="segmented" role="tablist" aria-label="选择应用">
|
||||||
className="segmented"
|
|
||||||
role="tablist"
|
|
||||||
aria-label="选择应用"
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
className="segmented-thumb"
|
className="segmented-thumb"
|
||||||
style={{
|
style={{
|
||||||
transform:
|
transform:
|
||||||
activeApp === "claude" ? "translateX(0%)" : "translateX(100%)",
|
activeApp === "claude"
|
||||||
|
? "translateX(0%)"
|
||||||
|
: "translateX(100%)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
const [codexConfig, setCodexConfig] = useState("");
|
const [codexConfig, setCodexConfig] = useState("");
|
||||||
const [codexApiKey, setCodexApiKey] = useState("");
|
const [codexApiKey, setCodexApiKey] = useState("");
|
||||||
const [selectedCodexPreset, setSelectedCodexPreset] = useState<number | null>(
|
const [selectedCodexPreset, setSelectedCodexPreset] = useState<number | null>(
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 初始化 Codex 配置
|
// 初始化 Codex 配置
|
||||||
@@ -151,7 +151,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (
|
const handleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
) => {
|
) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
// 更新JSON配置
|
// 更新JSON配置
|
||||||
const updatedConfig = updateCoAuthoredSetting(
|
const updatedConfig = updateCoAuthoredSetting(
|
||||||
formData.settingsConfig,
|
formData.settingsConfig,
|
||||||
checked
|
checked,
|
||||||
);
|
);
|
||||||
setFormData({
|
setFormData({
|
||||||
...formData,
|
...formData,
|
||||||
@@ -219,7 +219,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
// Codex: 应用预设
|
// Codex: 应用预设
|
||||||
const applyCodexPreset = (
|
const applyCodexPreset = (
|
||||||
preset: (typeof codexProviderPresets)[0],
|
preset: (typeof codexProviderPresets)[0],
|
||||||
index: number
|
index: number,
|
||||||
) => {
|
) => {
|
||||||
const authString = JSON.stringify(preset.auth || {}, null, 2);
|
const authString = JSON.stringify(preset.auth || {}, null, 2);
|
||||||
setCodexAuth(authString);
|
setCodexAuth(authString);
|
||||||
@@ -244,7 +244,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
const configString = setApiKeyInConfig(
|
const configString = setApiKeyInConfig(
|
||||||
formData.settingsConfig,
|
formData.settingsConfig,
|
||||||
key.trim(),
|
key.trim(),
|
||||||
{ createIfMissing: selectedPreset !== null }
|
{ createIfMissing: selectedPreset !== null },
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新表单配置
|
// 更新表单配置
|
||||||
@@ -298,7 +298,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialData) {
|
if (initialData) {
|
||||||
const parsedKey = getApiKeyFromConfig(
|
const parsedKey = getApiKeyFromConfig(
|
||||||
JSON.stringify(initialData.settingsConfig)
|
JSON.stringify(initialData.settingsConfig),
|
||||||
);
|
);
|
||||||
if (parsedKey) setApiKey(parsedKey);
|
if (parsedKey) setApiKey(parsedKey);
|
||||||
}
|
}
|
||||||
@@ -447,7 +447,9 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
: "只需要填这里,下方 auth.json 会自动填充"
|
: "只需要填这里,下方 auth.json 会自动填充"
|
||||||
}
|
}
|
||||||
disabled={isCodexOfficialPreset}
|
disabled={isCodexOfficialPreset}
|
||||||
required={selectedCodexPreset !== null && !isCodexOfficialPreset}
|
required={
|
||||||
|
selectedCodexPreset !== null && !isCodexOfficialPreset
|
||||||
|
}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
style={
|
style={
|
||||||
isCodexOfficialPreset
|
isCodexOfficialPreset
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const codexProviderPresets: CodexProviderPreset[] = [
|
|||||||
isOfficial: true,
|
isOfficial: true,
|
||||||
// 官方的 key 为null
|
// 官方的 key 为null
|
||||||
auth: {
|
auth: {
|
||||||
"OPENAI_API_KEY": null,
|
OPENAI_API_KEY: null,
|
||||||
},
|
},
|
||||||
config: ``,
|
config: ``,
|
||||||
},
|
},
|
||||||
@@ -25,7 +25,7 @@ export const codexProviderPresets: CodexProviderPreset[] = [
|
|||||||
websiteUrl: "https://codex.packycode.com/",
|
websiteUrl: "https://codex.packycode.com/",
|
||||||
// PackyCode 一般通过 API Key;请将占位符替换为你的实际 key
|
// PackyCode 一般通过 API Key;请将占位符替换为你的实际 key
|
||||||
auth: {
|
auth: {
|
||||||
"OPENAI_API_KEY": "sk-your-api-key-here",
|
OPENAI_API_KEY: "sk-your-api-key-here",
|
||||||
},
|
},
|
||||||
config: `model_provider = "packycode"
|
config: `model_provider = "packycode"
|
||||||
model = "gpt-5"
|
model = "gpt-5"
|
||||||
@@ -38,4 +38,3 @@ wire_api = "responses"
|
|||||||
env_key = "packycode"`,
|
env_key = "packycode"`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,11 @@ export const tauriAPI = {
|
|||||||
app?: AppType,
|
app?: AppType,
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
return await invoke("switch_provider", { id: providerId, app_type: app, app });
|
return await invoke("switch_provider", {
|
||||||
|
id: providerId,
|
||||||
|
app_type: app,
|
||||||
|
app,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("切换供应商失败:", error);
|
console.error("切换供应商失败:", error);
|
||||||
return false;
|
return false;
|
||||||
@@ -90,7 +94,10 @@ export const tauriAPI = {
|
|||||||
app?: AppType,
|
app?: AppType,
|
||||||
): Promise<ImportResult> => {
|
): Promise<ImportResult> => {
|
||||||
try {
|
try {
|
||||||
const success = await invoke<boolean>("import_default_config", { app_type: app, app });
|
const success = await invoke<boolean>("import_default_config", {
|
||||||
|
app_type: app,
|
||||||
|
app,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
success,
|
success,
|
||||||
message: success ? "成功导入默认配置" : "导入失败",
|
message: success ? "成功导入默认配置" : "导入失败",
|
||||||
|
|||||||
Reference in New Issue
Block a user