- fix(linux): disable modal backdrop blur on Linux (WebKitGTK/Wayland) to prevent freeze when opening Add Provider panel
- refactor(ui): add runtime platform detector and conditionally apply blur only on non-Linux platforms - chore: verify typecheck and renderer build succeed; no functional regression expected
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { AlertTriangle, X } from "lucide-react";
|
import { AlertTriangle, X } from "lucide-react";
|
||||||
|
import { isLinux } from "../lib/platform";
|
||||||
|
|
||||||
interface ConfirmDialogProps {
|
interface ConfirmDialogProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -26,7 +27,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|||||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
|
className={`absolute inset-0 bg-black/50${isLinux() ? "" : " backdrop-blur-sm"}`}
|
||||||
onClick={onCancel}
|
onClick={onCancel}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import ClaudeConfigEditor from "./ProviderForm/ClaudeConfigEditor";
|
|||||||
import CodexConfigEditor from "./ProviderForm/CodexConfigEditor";
|
import CodexConfigEditor from "./ProviderForm/CodexConfigEditor";
|
||||||
import KimiModelSelector from "./ProviderForm/KimiModelSelector";
|
import KimiModelSelector from "./ProviderForm/KimiModelSelector";
|
||||||
import { X, AlertCircle, Save } from "lucide-react";
|
import { X, AlertCircle, Save } from "lucide-react";
|
||||||
|
import { isLinux } from "../lib/platform";
|
||||||
// 分类仅用于控制少量交互(如官方禁用 API Key),不显示介绍组件
|
// 分类仅用于控制少量交互(如官方禁用 API Key),不显示介绍组件
|
||||||
|
|
||||||
const COMMON_CONFIG_STORAGE_KEY = "cc-switch:common-config-snippet";
|
const COMMON_CONFIG_STORAGE_KEY = "cc-switch:common-config-snippet";
|
||||||
@@ -966,7 +967,11 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
|
<div
|
||||||
|
className={`absolute inset-0 bg-black/50 dark:bg-black/70${
|
||||||
|
isLinux() ? "" : " backdrop-blur-sm"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Modal */}
|
{/* Modal */}
|
||||||
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-3xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-3xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import JsonEditor from "../JsonEditor";
|
import JsonEditor from "../JsonEditor";
|
||||||
import { X, Save } from "lucide-react";
|
import { X, Save } from "lucide-react";
|
||||||
|
import { isLinux } from "../../lib/platform";
|
||||||
|
|
||||||
interface ClaudeConfigEditorProps {
|
interface ClaudeConfigEditorProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -133,7 +134,11 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Backdrop - 统一背景样式 */}
|
{/* Backdrop - 统一背景样式 */}
|
||||||
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
|
<div
|
||||||
|
className={`absolute inset-0 bg-black/50 dark:bg-black/70${
|
||||||
|
isLinux() ? "" : " backdrop-blur-sm"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Modal - 统一窗口样式 */}
|
{/* Modal - 统一窗口样式 */}
|
||||||
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { X, Save } from "lucide-react";
|
import { X, Save } from "lucide-react";
|
||||||
|
import { isLinux } from "../../lib/platform";
|
||||||
|
|
||||||
interface CodexConfigEditorProps {
|
interface CodexConfigEditorProps {
|
||||||
authValue: string;
|
authValue: string;
|
||||||
@@ -166,7 +167,11 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Backdrop - 统一背景样式 */}
|
{/* Backdrop - 统一背景样式 */}
|
||||||
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
|
<div
|
||||||
|
className={`absolute inset-0 bg-black/50 dark:bg-black/70${
|
||||||
|
isLinux() ? "" : " backdrop-blur-sm"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Modal - 统一窗口样式 */}
|
{/* Modal - 统一窗口样式 */}
|
||||||
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import "../lib/tauri-api";
|
|||||||
import { relaunchApp } from "../lib/updater";
|
import { relaunchApp } from "../lib/updater";
|
||||||
import { useUpdate } from "../contexts/UpdateContext";
|
import { useUpdate } from "../contexts/UpdateContext";
|
||||||
import type { Settings } from "../types";
|
import type { Settings } from "../types";
|
||||||
|
import { isLinux } from "../lib/platform";
|
||||||
|
|
||||||
interface SettingsModalProps {
|
interface SettingsModalProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -163,7 +164,11 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
|
|||||||
if (e.target === e.currentTarget) onClose();
|
if (e.target === e.currentTarget) onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
|
<div
|
||||||
|
className={`absolute inset-0 bg-black/50 dark:bg-black/70${
|
||||||
|
isLinux() ? "" : " backdrop-blur-sm"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-2xl w-[500px] overflow-hidden">
|
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-2xl w-[500px] overflow-hidden">
|
||||||
{/* 标题栏 */}
|
{/* 标题栏 */}
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-800">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-800">
|
||||||
|
|||||||
30
src/lib/platform.ts
Normal file
30
src/lib/platform.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 轻量平台检测,避免在 SSR 或无 navigator 的环境报错
|
||||||
|
export const isMac = (): boolean => {
|
||||||
|
try {
|
||||||
|
const ua = navigator.userAgent || "";
|
||||||
|
const plat = (navigator.platform || "").toLowerCase();
|
||||||
|
return /mac/i.test(ua) || plat.includes("mac");
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isWindows = (): boolean => {
|
||||||
|
try {
|
||||||
|
const ua = navigator.userAgent || "";
|
||||||
|
return /windows|win32|win64/i.test(ua);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isLinux = (): boolean => {
|
||||||
|
try {
|
||||||
|
const ua = navigator.userAgent || "";
|
||||||
|
// WebKitGTK/Chromium 在 Linux/Wayland/X11 下 UA 通常包含 Linux 或 X11
|
||||||
|
return /linux|x11/i.test(ua) && !/android/i.test(ua) && !isMac() && !isWindows();
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Reference in New Issue
Block a user