mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-28 07:25:53 +00:00
Merge branch 'dev' of https://github.com/hicccc77/WeFlow into dev
This commit is contained in:
@@ -7611,6 +7611,12 @@ function MessageBubble({
|
||||
const [voiceWaveform, setVoiceWaveform] = useState<number[]>([])
|
||||
const voiceAutoDecryptTriggered = useRef(false)
|
||||
|
||||
|
||||
const [systemAlert, setSystemAlert] = useState<{
|
||||
title: string;
|
||||
message: React.ReactNode;
|
||||
} | null>(null)
|
||||
|
||||
// 转账消息双方名称
|
||||
const [transferPayerName, setTransferPayerName] = useState<string | undefined>(undefined)
|
||||
const [transferReceiverName, setTransferReceiverName] = useState<string | undefined>(undefined)
|
||||
@@ -8290,9 +8296,9 @@ function MessageBubble({
|
||||
}
|
||||
|
||||
const result = await window.electronAPI.chat.getVoiceTranscript(
|
||||
session.username,
|
||||
String(message.localId),
|
||||
message.createTime
|
||||
session.username,
|
||||
String(message.localId),
|
||||
message.createTime
|
||||
)
|
||||
|
||||
if (result.success) {
|
||||
@@ -8300,6 +8306,21 @@ function MessageBubble({
|
||||
voiceTranscriptCache.set(voiceTranscriptCacheKey, transcriptText)
|
||||
setVoiceTranscript(transcriptText)
|
||||
} else {
|
||||
if (result.error === 'SEGFAULT_ERROR') {
|
||||
console.warn('[ChatPage] 捕获到语音引擎底层段错误');
|
||||
|
||||
setSystemAlert({
|
||||
title: '引擎崩溃提示',
|
||||
message: (
|
||||
<>
|
||||
语音识别引擎发生底层崩溃 (Segmentation Fault)。<br /><br />
|
||||
如果您使用的是 Linux 等自定义程度较高的系统,请检查 <code>sherpa-onnx</code> 的相关系统动态链接库 (如 glibc 等) 是否兼容。
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setVoiceTranscriptError(true)
|
||||
voiceTranscriptRequestedRef.current = false
|
||||
}
|
||||
@@ -9699,6 +9720,31 @@ function MessageBubble({
|
||||
{isSelected && <Check size={14} strokeWidth={3} />}
|
||||
</div>
|
||||
)}
|
||||
{systemAlert && createPortal(
|
||||
<div className="modal-overlay" onClick={() => setSystemAlert(null)} style={{ zIndex: 99999 }}>
|
||||
<div className="delete-confirm-card" onClick={(e) => e.stopPropagation()} style={{ maxWidth: '400px' }}>
|
||||
<div className="confirm-icon">
|
||||
<AlertCircle size={32} color="var(--danger)" />
|
||||
</div>
|
||||
<div className="confirm-content">
|
||||
<h3>{systemAlert.title}</h3>
|
||||
<p style={{ marginTop: '12px', lineHeight: '1.6', fontSize: '14px', color: 'var(--text-secondary)' }}>
|
||||
{systemAlert.message}
|
||||
</p>
|
||||
</div>
|
||||
<div className="confirm-actions" style={{ justifyContent: 'center', marginTop: '24px' }}>
|
||||
<button
|
||||
className="btn-primary"
|
||||
onClick={() => setSystemAlert(null)}
|
||||
style={{ padding: '8px 32px' }}
|
||||
>
|
||||
确认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -175,6 +175,21 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
||||
|
||||
const isClearingCache = isClearingAnalyticsCache || isClearingImageCache || isClearingAllCache
|
||||
|
||||
const [isWayland, setIsWayland] = useState(false)
|
||||
useEffect(() => {
|
||||
const checkWaylandStatus = async () => {
|
||||
if (window.electronAPI?.app?.checkWayland) {
|
||||
try {
|
||||
const wayland = await window.electronAPI.app.checkWayland()
|
||||
setIsWayland(wayland)
|
||||
} catch (e) {
|
||||
console.error('检查 Wayland 状态失败:', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
checkWaylandStatus()
|
||||
}, [])
|
||||
|
||||
// 检查 Hello 可用性
|
||||
useEffect(() => {
|
||||
if (window.PublicKeyCredential) {
|
||||
@@ -1169,6 +1184,11 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
||||
<div className="form-group">
|
||||
<label>通知显示位置</label>
|
||||
<span className="form-hint">选择通知弹窗在屏幕上的显示位置</span>
|
||||
{isWayland && (
|
||||
<span className="form-hint" style={{ color: '#ff4d4f', marginTop: '4px', display: 'block' }}>
|
||||
⚠️ 注意:Wayland 环境下该配置可能无效!
|
||||
</span>
|
||||
)}
|
||||
<div className="custom-select">
|
||||
<div
|
||||
className={`custom-select-trigger ${positionDropdownOpen ? 'open' : ''}`}
|
||||
@@ -1652,34 +1672,49 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
||||
)
|
||||
|
||||
const renderCacheTab = () => (
|
||||
<div className="tab-content">
|
||||
<p className="section-desc">管理应用缓存数据</p>
|
||||
<div className="form-group">
|
||||
<label>缓存目录 <span className="optional">(可选)</span></label>
|
||||
<span className="form-hint">留空使用默认目录</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="留空使用默认目录"
|
||||
value={cachePath}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
setCachePath(value)
|
||||
scheduleConfigSave('cachePath', () => configService.setCachePath(value))
|
||||
}}
|
||||
/>
|
||||
<div className="btn-row">
|
||||
<button className="btn btn-secondary" onClick={handleSelectCachePath}><FolderOpen size={16} /> 浏览选择</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={async () => {
|
||||
setCachePath('')
|
||||
await configService.setCachePath('')
|
||||
}}
|
||||
>
|
||||
<RotateCcw size={16} /> 恢复默认
|
||||
</button>
|
||||
<div className="tab-content">
|
||||
<p className="section-desc">管理应用缓存数据</p>
|
||||
<div className="form-group">
|
||||
<label>缓存目录 <span className="optional">(可选)</span></label>
|
||||
<span className="form-hint">留空使用默认目录</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="留空使用默认目录"
|
||||
value={cachePath}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value
|
||||
setCachePath(value)
|
||||
scheduleConfigSave('cachePath', () => configService.setCachePath(value))
|
||||
}}
|
||||
/>
|
||||
|
||||
<div style={{ marginTop: '8px', fontSize: '13px', color: 'var(--text-secondary)' }}>
|
||||
当前缓存位置:
|
||||
<code style={{
|
||||
background: 'var(--bg-secondary)',
|
||||
padding: '3px 6px',
|
||||
borderRadius: '4px',
|
||||
userSelect: 'all',
|
||||
wordBreak: 'break-all',
|
||||
marginLeft: '4px'
|
||||
}}>
|
||||
{cachePath || (isMac ? '~/Documents/WeFlow' : isLinux ? '~/Documents/WeFlow' : '系统 文档\\WeFlow 目录')}
|
||||
</code>
|
||||
</div>
|
||||
|
||||
<div className="btn-row" style={{ marginTop: '12px' }}>
|
||||
<button className="btn btn-secondary" onClick={handleSelectCachePath}><FolderOpen size={16} /> 浏览选择</button>
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={async () => {
|
||||
setCachePath('')
|
||||
await configService.setCachePath('')
|
||||
}}
|
||||
>
|
||||
<RotateCcw size={16} /> 恢复默认
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="btn-row">
|
||||
<button className="btn btn-secondary" onClick={handleClearAnalyticsCache} disabled={isClearingCache}>
|
||||
|
||||
Reference in New Issue
Block a user