mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
Merge branch 'hicccc77:dev' into dev
This commit is contained in:
@@ -768,7 +768,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
setIsRefreshingMessages(true)
|
||||
|
||||
// 找出当前已渲染消息中的最大时间戳(使用 getState 获取最新状态,避免闭包过时导致重复)
|
||||
const currentMessages = useChatStore.getState().messages
|
||||
const currentMessages = useChatStore.getState().messages || []
|
||||
const lastMsg = currentMessages[currentMessages.length - 1]
|
||||
const minTime = lastMsg?.createTime || 0
|
||||
|
||||
@@ -782,7 +782,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
|
||||
if (result.success && result.messages && result.messages.length > 0) {
|
||||
// 过滤去重:必须对比实时的状态,防止在 handleRefreshMessages 运行期间导致的冲突
|
||||
const latestMessages = useChatStore.getState().messages
|
||||
const latestMessages = useChatStore.getState().messages || []
|
||||
const existingKeys = new Set(latestMessages.map(getMessageKey))
|
||||
const newOnes = result.messages.filter(m => !existingKeys.has(getMessageKey(m)))
|
||||
|
||||
@@ -823,7 +823,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
return
|
||||
}
|
||||
// 使用实时状态进行去重对比
|
||||
const latestMessages = useChatStore.getState().messages
|
||||
const latestMessages = useChatStore.getState().messages || []
|
||||
const existing = new Set(latestMessages.map(getMessageKey))
|
||||
const lastMsg = latestMessages[latestMessages.length - 1]
|
||||
const lastTime = lastMsg?.createTime ?? 0
|
||||
@@ -1751,7 +1751,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
|
||||
// Range selection with Shift key
|
||||
if (isShiftKey && lastSelectedIdRef.current !== null && lastSelectedIdRef.current !== localId) {
|
||||
const currentMsgs = useChatStore.getState().messages
|
||||
const currentMsgs = useChatStore.getState().messages || []
|
||||
const idx1 = currentMsgs.findIndex(m => m.localId === lastSelectedIdRef.current)
|
||||
const idx2 = currentMsgs.findIndex(m => m.localId === localId)
|
||||
|
||||
@@ -1821,7 +1821,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
const dbPathHint = (msg as any)._db_path
|
||||
const result = await (window as any).electronAPI.chat.deleteMessage(currentSessionId, msg.localId, msg.createTime, dbPathHint)
|
||||
if (result.success) {
|
||||
const currentMessages = useChatStore.getState().messages
|
||||
const currentMessages = useChatStore.getState().messages || []
|
||||
const newMessages = currentMessages.filter(m => m.localId !== msg.localId)
|
||||
useChatStore.getState().setMessages(newMessages)
|
||||
} else {
|
||||
@@ -1882,7 +1882,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
try {
|
||||
const result = await (window as any).electronAPI.chat.updateMessage(currentSessionId, editingMessage.message.localId, editingMessage.message.createTime, finalContent)
|
||||
if (result.success) {
|
||||
const currentMessages = useChatStore.getState().messages
|
||||
const currentMessages = useChatStore.getState().messages || []
|
||||
const newMessages = currentMessages.map(m => {
|
||||
if (m.localId === editingMessage.message.localId) {
|
||||
return { ...m, parsedContent: finalContent, content: finalContent, rawContent: finalContent }
|
||||
@@ -1924,7 +1924,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
cancelDeleteRef.current = false
|
||||
|
||||
try {
|
||||
const currentMessages = useChatStore.getState().messages
|
||||
const currentMessages = useChatStore.getState().messages || []
|
||||
const selectedIds = Array.from(selectedMessages)
|
||||
const deletedIds = new Set<number>()
|
||||
|
||||
@@ -1948,7 +1948,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
setDeleteProgress({ current: i + 1, total: selectedIds.length })
|
||||
}
|
||||
|
||||
const finalMessages = useChatStore.getState().messages.filter(m => !deletedIds.has(m.localId))
|
||||
const finalMessages = (useChatStore.getState().messages || []).filter(m => !deletedIds.has(m.localId))
|
||||
useChatStore.getState().setMessages(finalMessages)
|
||||
|
||||
setIsSelectionMode(false)
|
||||
@@ -2137,7 +2137,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
<div className="empty-sessions">
|
||||
<MessageSquare />
|
||||
<p>暂无会话</p>
|
||||
<p className="hint">请先在数据管理页面解密数据库</p>
|
||||
<p className="hint">检查你的数据库配置</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -2342,7 +2342,7 @@ function ChatPage(_props: ChatPageProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{messages.map((msg, index) => {
|
||||
{(messages || []).map((msg, index) => {
|
||||
const prevMsg = index > 0 ? messages[index - 1] : undefined
|
||||
const showDateDivider = shouldShowDateDivider(msg, prevMsg)
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { NotificationToast, type NotificationData } from '../components/NotificationToast'
|
||||
import { useThemeStore } from '../stores/themeStore'
|
||||
import '../components/NotificationToast.scss'
|
||||
import './NotificationWindow.scss'
|
||||
|
||||
export default function NotificationWindow() {
|
||||
const { currentTheme, themeMode } = useThemeStore()
|
||||
const [notification, setNotification] = useState<NotificationData | null>(null)
|
||||
const [prevNotification, setPrevNotification] = useState<NotificationData | null>(null)
|
||||
|
||||
@@ -19,12 +17,6 @@ export default function NotificationWindow() {
|
||||
|
||||
const notificationRef = useRef<NotificationData | null>(null)
|
||||
|
||||
// 应用主题到通知窗口
|
||||
useEffect(() => {
|
||||
document.documentElement.setAttribute('data-theme', currentTheme)
|
||||
document.documentElement.setAttribute('data-mode', themeMode)
|
||||
}, [currentTheme, themeMode])
|
||||
|
||||
useEffect(() => {
|
||||
notificationRef.current = notification
|
||||
}, [notification])
|
||||
|
||||
@@ -774,7 +774,7 @@ function SettingsPage() {
|
||||
}
|
||||
setIsFetchingImageKey(true);
|
||||
setImageKeyPercent(0)
|
||||
setImageKeyStatus('正在初始化多核爆破引擎...');
|
||||
setImageKeyStatus('正在初始化...');
|
||||
setImageKeyProgress(0); // 重置进度
|
||||
|
||||
try {
|
||||
@@ -1377,19 +1377,19 @@ function SettingsPage() {
|
||||
<Plug size={14} /> {isFetchingImageKey ? '获取中...' : '自动获取图片密钥'}
|
||||
</button>
|
||||
{isFetchingImageKey ? (
|
||||
<div className="brute-force-progress">
|
||||
<div className="status-header">
|
||||
<span className="status-text">{imageKeyStatus || '正在启动多核爆破引擎...'}</span>
|
||||
{imageKeyPercent !== null && <span className="percent">{imageKeyPercent.toFixed(1)}%</span>}
|
||||
</div>
|
||||
{imageKeyPercent !== null && (
|
||||
<div className="progress-bar-container">
|
||||
<div className="fill" style={{ width: `${imageKeyPercent}%` }}></div>
|
||||
</div>
|
||||
)}
|
||||
<div className="brute-force-progress">
|
||||
<div className="status-header">
|
||||
<span className="status-text">{imageKeyStatus || '正在启动...'}</span>
|
||||
{imageKeyPercent !== null && <span className="percent">{imageKeyPercent.toFixed(1)}%</span>}
|
||||
</div>
|
||||
{imageKeyPercent !== null && (
|
||||
<div className="progress-bar-container">
|
||||
<div className="fill" style={{ width: `${imageKeyPercent}%` }}></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
imageKeyStatus && <div className="form-hint status-text" style={{ marginTop: '8px' }}>{imageKeyStatus}</div>
|
||||
imageKeyStatus && <div className="form-hint status-text" style={{ marginTop: '8px' }}>{imageKeyStatus}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2113,8 +2113,8 @@ function SettingsPage() {
|
||||
<label>应用锁状态</label>
|
||||
<span className="form-hint">{
|
||||
isLockMode ? '已开启' :
|
||||
authEnabled ? '旧版模式 — 请重新设置密码以升级为新模式提高安全性' :
|
||||
'未开启 — 请设置密码以开启'
|
||||
authEnabled ? '旧版模式 — 请重新设置密码以升级为新模式提高安全性' :
|
||||
'未开启 — 请设置密码以开启'
|
||||
}</span>
|
||||
</div>
|
||||
{authEnabled && !showDisableLockInput && (
|
||||
|
||||
@@ -746,52 +746,52 @@ function WelcomePage({ standalone = false }: WelcomePageProps) {
|
||||
)}
|
||||
|
||||
{currentStep.id === 'image' && (
|
||||
<div className="form-group">
|
||||
<div className="grid-2">
|
||||
<div>
|
||||
<label className="field-label">图片 XOR 密钥</label>
|
||||
<input
|
||||
type="text"
|
||||
className="field-input"
|
||||
placeholder="0x..."
|
||||
value={imageXorKey}
|
||||
onChange={(e) => setImageXorKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="field-label">图片 AES 密钥</label>
|
||||
<input
|
||||
type="text"
|
||||
className="field-input"
|
||||
placeholder="16位密钥"
|
||||
value={imageAesKey}
|
||||
onChange={(e) => setImageAesKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div className="grid-2">
|
||||
<div>
|
||||
<label className="field-label">图片 XOR 密钥</label>
|
||||
<input
|
||||
type="text"
|
||||
className="field-input"
|
||||
placeholder="0x..."
|
||||
value={imageXorKey}
|
||||
onChange={(e) => setImageXorKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="field-label">图片 AES 密钥</label>
|
||||
<input
|
||||
type="text"
|
||||
className="field-input"
|
||||
placeholder="16位密钥"
|
||||
value={imageAesKey}
|
||||
onChange={(e) => setImageAesKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button className="btn btn-secondary btn-block mt-4" onClick={handleAutoGetImageKey} disabled={isFetchingImageKey}>
|
||||
{isFetchingImageKey ? '获取中...' : '自动获取图片密钥'}
|
||||
</button>
|
||||
|
||||
{isFetchingImageKey ? (
|
||||
<div className="brute-force-progress">
|
||||
<div className="status-header">
|
||||
<span className="status-text">{imageKeyStatus || '正在启动多核爆破引擎...'}</span>
|
||||
{imageKeyPercent !== null && <span className="percent">{imageKeyPercent.toFixed(1)}%</span>}
|
||||
</div>
|
||||
{imageKeyPercent !== null && (
|
||||
<div className="progress-bar-container">
|
||||
<div className="fill" style={{ width: `${imageKeyPercent}%` }}></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
imageKeyStatus && <div className="status-message" style={{ marginTop: '12px' }}>{imageKeyStatus}</div>
|
||||
)}
|
||||
|
||||
<div className="field-hint">请在微信中打开几张图片后再点击获取</div>
|
||||
</div>
|
||||
|
||||
<button className="btn btn-secondary btn-block mt-4" onClick={handleAutoGetImageKey} disabled={isFetchingImageKey}>
|
||||
{isFetchingImageKey ? '获取中...' : '自动获取图片密钥'}
|
||||
</button>
|
||||
|
||||
{isFetchingImageKey ? (
|
||||
<div className="brute-force-progress">
|
||||
<div className="status-header">
|
||||
<span className="status-text">{imageKeyStatus || '正在启动...'}</span>
|
||||
{imageKeyPercent !== null && <span className="percent">{imageKeyPercent.toFixed(1)}%</span>}
|
||||
</div>
|
||||
{imageKeyPercent !== null && (
|
||||
<div className="progress-bar-container">
|
||||
<div className="fill" style={{ width: `${imageKeyPercent}%` }}></div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
imageKeyStatus && <div className="status-message" style={{ marginTop: '12px' }}>{imageKeyStatus}</div>
|
||||
)}
|
||||
|
||||
<div className="field-hint">请在微信中打开几张图片后再点击获取</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user