mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
feat(export): add open-chat window from session list
This commit is contained in:
@@ -85,6 +85,7 @@ let agreementWindow: BrowserWindow | null = null
|
|||||||
let onboardingWindow: BrowserWindow | null = null
|
let onboardingWindow: BrowserWindow | null = null
|
||||||
// Splash 启动窗口
|
// Splash 启动窗口
|
||||||
let splashWindow: BrowserWindow | null = null
|
let splashWindow: BrowserWindow | null = null
|
||||||
|
const sessionChatWindows = new Map<string, BrowserWindow>()
|
||||||
const keyService = new KeyService()
|
const keyService = new KeyService()
|
||||||
|
|
||||||
let mainWindowReady = false
|
let mainWindowReady = false
|
||||||
@@ -683,6 +684,87 @@ function createChatHistoryWindow(sessionId: string, messageId: number) {
|
|||||||
return win
|
return win
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建独立的会话聊天窗口(单会话,复用聊天页右侧消息区域)
|
||||||
|
*/
|
||||||
|
function createSessionChatWindow(sessionId: string) {
|
||||||
|
const normalizedSessionId = String(sessionId || '').trim()
|
||||||
|
if (!normalizedSessionId) return null
|
||||||
|
|
||||||
|
const existing = sessionChatWindows.get(normalizedSessionId)
|
||||||
|
if (existing && !existing.isDestroyed()) {
|
||||||
|
if (existing.isMinimized()) {
|
||||||
|
existing.restore()
|
||||||
|
}
|
||||||
|
existing.focus()
|
||||||
|
return existing
|
||||||
|
}
|
||||||
|
|
||||||
|
const isDev = !!process.env.VITE_DEV_SERVER_URL
|
||||||
|
const iconPath = isDev
|
||||||
|
? join(__dirname, '../public/icon.ico')
|
||||||
|
: join(process.resourcesPath, 'icon.ico')
|
||||||
|
|
||||||
|
const isDark = nativeTheme.shouldUseDarkColors
|
||||||
|
|
||||||
|
const win = new BrowserWindow({
|
||||||
|
width: 980,
|
||||||
|
height: 820,
|
||||||
|
minWidth: 560,
|
||||||
|
minHeight: 560,
|
||||||
|
icon: iconPath,
|
||||||
|
webPreferences: {
|
||||||
|
preload: join(__dirname, 'preload.js'),
|
||||||
|
contextIsolation: true,
|
||||||
|
nodeIntegration: false
|
||||||
|
},
|
||||||
|
titleBarStyle: 'hidden',
|
||||||
|
titleBarOverlay: {
|
||||||
|
color: '#00000000',
|
||||||
|
symbolColor: isDark ? '#ffffff' : '#1a1a1a',
|
||||||
|
height: 40
|
||||||
|
},
|
||||||
|
show: false,
|
||||||
|
backgroundColor: isDark ? '#1A1A1A' : '#F0F0F0',
|
||||||
|
autoHideMenuBar: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const sessionParam = `sessionId=${encodeURIComponent(normalizedSessionId)}`
|
||||||
|
if (process.env.VITE_DEV_SERVER_URL) {
|
||||||
|
win.loadURL(`${process.env.VITE_DEV_SERVER_URL}#/chat-window?${sessionParam}`)
|
||||||
|
|
||||||
|
win.webContents.on('before-input-event', (event, input) => {
|
||||||
|
if (input.key === 'F12' || (input.control && input.shift && input.key === 'I')) {
|
||||||
|
if (win.webContents.isDevToolsOpened()) {
|
||||||
|
win.webContents.closeDevTools()
|
||||||
|
} else {
|
||||||
|
win.webContents.openDevTools()
|
||||||
|
}
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
win.loadFile(join(__dirname, '../dist/index.html'), {
|
||||||
|
hash: `/chat-window?${sessionParam}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
win.once('ready-to-show', () => {
|
||||||
|
win.show()
|
||||||
|
win.focus()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('closed', () => {
|
||||||
|
const tracked = sessionChatWindows.get(normalizedSessionId)
|
||||||
|
if (tracked === win) {
|
||||||
|
sessionChatWindows.delete(normalizedSessionId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
sessionChatWindows.set(normalizedSessionId, win)
|
||||||
|
return win
|
||||||
|
}
|
||||||
|
|
||||||
function showMainWindow() {
|
function showMainWindow() {
|
||||||
shouldShowMain = true
|
shouldShowMain = true
|
||||||
if (mainWindowReady) {
|
if (mainWindowReady) {
|
||||||
@@ -915,6 +997,12 @@ function registerIpcHandlers() {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 打开会话聊天窗口(同会话仅保留一个窗口并聚焦)
|
||||||
|
ipcMain.handle('window:openSessionChatWindow', (_, sessionId: string) => {
|
||||||
|
const win = createSessionChatWindow(sessionId)
|
||||||
|
return Boolean(win)
|
||||||
|
})
|
||||||
|
|
||||||
// 根据视频尺寸调整窗口大小
|
// 根据视频尺寸调整窗口大小
|
||||||
ipcMain.handle('window:resizeToFitVideo', (event, videoWidth: number, videoHeight: number) => {
|
ipcMain.handle('window:resizeToFitVideo', (event, videoWidth: number, videoHeight: number) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender)
|
const win = BrowserWindow.fromWebContents(event.sender)
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||||||
openImageViewerWindow: (imagePath: string, liveVideoPath?: string) =>
|
openImageViewerWindow: (imagePath: string, liveVideoPath?: string) =>
|
||||||
ipcRenderer.invoke('window:openImageViewerWindow', imagePath, liveVideoPath),
|
ipcRenderer.invoke('window:openImageViewerWindow', imagePath, liveVideoPath),
|
||||||
openChatHistoryWindow: (sessionId: string, messageId: number) =>
|
openChatHistoryWindow: (sessionId: string, messageId: number) =>
|
||||||
ipcRenderer.invoke('window:openChatHistoryWindow', sessionId, messageId)
|
ipcRenderer.invoke('window:openChatHistoryWindow', sessionId, messageId),
|
||||||
|
openSessionChatWindow: (sessionId: string) =>
|
||||||
|
ipcRenderer.invoke('window:openSessionChatWindow', sessionId)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 数据库路径
|
// 数据库路径
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ function App() {
|
|||||||
const isOnboardingWindow = location.pathname === '/onboarding-window'
|
const isOnboardingWindow = location.pathname === '/onboarding-window'
|
||||||
const isVideoPlayerWindow = location.pathname === '/video-player-window'
|
const isVideoPlayerWindow = location.pathname === '/video-player-window'
|
||||||
const isChatHistoryWindow = location.pathname.startsWith('/chat-history/')
|
const isChatHistoryWindow = location.pathname.startsWith('/chat-history/')
|
||||||
|
const isStandaloneChatWindow = location.pathname === '/chat-window'
|
||||||
const isNotificationWindow = location.pathname === '/notification-window'
|
const isNotificationWindow = location.pathname === '/notification-window'
|
||||||
const isExportRoute = location.pathname === '/export'
|
const isExportRoute = location.pathname === '/export'
|
||||||
const [themeHydrated, setThemeHydrated] = useState(false)
|
const [themeHydrated, setThemeHydrated] = useState(false)
|
||||||
@@ -361,6 +362,12 @@ function App() {
|
|||||||
return <ChatHistoryPage />
|
return <ChatHistoryPage />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 独立会话聊天窗口(仅显示聊天内容区域)
|
||||||
|
if (isStandaloneChatWindow) {
|
||||||
|
const sessionId = new URLSearchParams(location.search).get('sessionId') || ''
|
||||||
|
return <ChatPage standaloneSessionWindow initialSessionId={sessionId} />
|
||||||
|
}
|
||||||
|
|
||||||
// 独立通知窗口
|
// 独立通知窗口
|
||||||
if (isNotificationWindow) {
|
if (isNotificationWindow) {
|
||||||
return <NotificationWindow />
|
return <NotificationWindow />
|
||||||
|
|||||||
@@ -202,7 +202,8 @@ function formatYmdHmDateTime(timestamp?: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ChatPageProps {
|
interface ChatPageProps {
|
||||||
// 保留接口以备将来扩展
|
standaloneSessionWindow?: boolean
|
||||||
|
initialSessionId?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -403,7 +404,9 @@ const SessionItem = React.memo(function SessionItem({
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ChatPage(_props: ChatPageProps) {
|
function ChatPage(props: ChatPageProps) {
|
||||||
|
const { standaloneSessionWindow = false, initialSessionId = null } = props
|
||||||
|
const normalizedInitialSessionId = useMemo(() => String(initialSessionId || '').trim(), [initialSessionId])
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -2223,34 +2226,30 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
}, [appendMessages, getMessageKey])
|
}, [appendMessages, getMessageKey])
|
||||||
|
|
||||||
// 选择会话
|
// 选择会话
|
||||||
const handleSelectSession = (session: ChatSession) => {
|
const selectSessionById = useCallback((sessionId: string) => {
|
||||||
// 点击折叠群入口,切换到折叠群视图
|
const normalizedSessionId = String(sessionId || '').trim()
|
||||||
if (session.username.toLowerCase().includes('placeholder_foldgroup')) {
|
if (!normalizedSessionId || normalizedSessionId === currentSessionId) return
|
||||||
setFoldedView(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (session.username === currentSessionId) return
|
|
||||||
const switchRequestSeq = sessionSwitchRequestSeqRef.current + 1
|
const switchRequestSeq = sessionSwitchRequestSeqRef.current + 1
|
||||||
sessionSwitchRequestSeqRef.current = switchRequestSeq
|
sessionSwitchRequestSeqRef.current = switchRequestSeq
|
||||||
|
|
||||||
setCurrentSession(session.username, { preserveMessages: false })
|
setCurrentSession(normalizedSessionId, { preserveMessages: false })
|
||||||
setNoMessageTable(false)
|
setNoMessageTable(false)
|
||||||
|
|
||||||
const restoredFromWindowCache = restoreSessionWindowCache(session.username)
|
const restoredFromWindowCache = restoreSessionWindowCache(normalizedSessionId)
|
||||||
if (restoredFromWindowCache) {
|
if (restoredFromWindowCache) {
|
||||||
pendingSessionLoadRef.current = null
|
pendingSessionLoadRef.current = null
|
||||||
initialLoadRequestedSessionRef.current = null
|
initialLoadRequestedSessionRef.current = null
|
||||||
setIsSessionSwitching(false)
|
setIsSessionSwitching(false)
|
||||||
void refreshSessionIncrementally(session.username, switchRequestSeq)
|
void refreshSessionIncrementally(normalizedSessionId, switchRequestSeq)
|
||||||
} else {
|
} else {
|
||||||
pendingSessionLoadRef.current = session.username
|
pendingSessionLoadRef.current = normalizedSessionId
|
||||||
initialLoadRequestedSessionRef.current = session.username
|
initialLoadRequestedSessionRef.current = normalizedSessionId
|
||||||
setIsSessionSwitching(true)
|
setIsSessionSwitching(true)
|
||||||
void hydrateSessionPreview(session.username)
|
void hydrateSessionPreview(normalizedSessionId)
|
||||||
setCurrentOffset(0)
|
setCurrentOffset(0)
|
||||||
setJumpStartTime(0)
|
setJumpStartTime(0)
|
||||||
setJumpEndTime(0)
|
setJumpEndTime(0)
|
||||||
void loadMessages(session.username, 0, 0, 0, false, {
|
void loadMessages(normalizedSessionId, 0, 0, 0, false, {
|
||||||
preferLatestPath: true,
|
preferLatestPath: true,
|
||||||
deferGroupSenderWarmup: true,
|
deferGroupSenderWarmup: true,
|
||||||
forceInitialLimit: 30,
|
forceInitialLimit: 30,
|
||||||
@@ -2269,6 +2268,23 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
setSessionDetail(null)
|
setSessionDetail(null)
|
||||||
setIsRefreshingDetailStats(false)
|
setIsRefreshingDetailStats(false)
|
||||||
setIsLoadingRelationStats(false)
|
setIsLoadingRelationStats(false)
|
||||||
|
}, [
|
||||||
|
currentSessionId,
|
||||||
|
setCurrentSession,
|
||||||
|
restoreSessionWindowCache,
|
||||||
|
refreshSessionIncrementally,
|
||||||
|
hydrateSessionPreview,
|
||||||
|
loadMessages
|
||||||
|
])
|
||||||
|
|
||||||
|
// 选择会话
|
||||||
|
const handleSelectSession = (session: ChatSession) => {
|
||||||
|
// 点击折叠群入口,切换到折叠群视图
|
||||||
|
if (session.username.toLowerCase().includes('placeholder_foldgroup')) {
|
||||||
|
setFoldedView(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectSessionById(session.username)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索过滤
|
// 搜索过滤
|
||||||
@@ -2698,6 +2714,21 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
const isCurrentSessionExporting = Boolean(currentSessionId && inProgressExportSessionIds.has(currentSessionId))
|
const isCurrentSessionExporting = Boolean(currentSessionId && inProgressExportSessionIds.has(currentSessionId))
|
||||||
const isExportActionBusy = isCurrentSessionExporting || isPreparingExportDialog
|
const isExportActionBusy = isCurrentSessionExporting || isPreparingExportDialog
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!standaloneSessionWindow) return
|
||||||
|
if (!normalizedInitialSessionId) return
|
||||||
|
if (!isConnected || isConnecting) return
|
||||||
|
if (currentSessionId === normalizedInitialSessionId) return
|
||||||
|
selectSessionById(normalizedInitialSessionId)
|
||||||
|
}, [
|
||||||
|
standaloneSessionWindow,
|
||||||
|
normalizedInitialSessionId,
|
||||||
|
isConnected,
|
||||||
|
isConnecting,
|
||||||
|
currentSessionId,
|
||||||
|
selectSessionById
|
||||||
|
])
|
||||||
|
|
||||||
// 从通讯录跳转时,会话不在列表中,主动加载联系人显示名称
|
// 从通讯录跳转时,会话不在列表中,主动加载联系人显示名称
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentSessionId) return
|
if (!currentSessionId) return
|
||||||
@@ -3264,7 +3295,7 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`chat-page ${isResizing ? 'resizing' : ''}`}>
|
<div className={`chat-page ${isResizing ? 'resizing' : ''} ${standaloneSessionWindow ? 'standalone session-only' : ''}`}>
|
||||||
{/* 自定义删除确认对话框 */}
|
{/* 自定义删除确认对话框 */}
|
||||||
{deleteConfirm.show && (
|
{deleteConfirm.show && (
|
||||||
<div className="delete-confirm-overlay">
|
<div className="delete-confirm-overlay">
|
||||||
@@ -3336,6 +3367,7 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* 左侧会话列表 */}
|
{/* 左侧会话列表 */}
|
||||||
|
{!standaloneSessionWindow && (
|
||||||
<div
|
<div
|
||||||
className="session-sidebar"
|
className="session-sidebar"
|
||||||
ref={sidebarRef}
|
ref={sidebarRef}
|
||||||
@@ -3470,9 +3502,10 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 拖动调节条 */}
|
{/* 拖动调节条 */}
|
||||||
<div className="resize-handle" onMouseDown={handleResizeStart} />
|
{!standaloneSessionWindow && <div className="resize-handle" onMouseDown={handleResizeStart} />}
|
||||||
|
|
||||||
{/* 右侧消息区域 */}
|
{/* 右侧消息区域 */}
|
||||||
<div className="message-area">
|
<div className="message-area">
|
||||||
@@ -4052,7 +4085,8 @@ function ChatPage(_props: ChatPageProps) {
|
|||||||
) : (
|
) : (
|
||||||
<div className="empty-chat">
|
<div className="empty-chat">
|
||||||
<MessageSquare />
|
<MessageSquare />
|
||||||
<p>选择一个会话开始查看聊天记录</p>
|
<p>{standaloneSessionWindow ? '会话加载中或暂无会话记录' : '选择一个会话开始查看聊天记录'}</p>
|
||||||
|
{standaloneSessionWindow && connectionError && <p className="hint">{connectionError}</p>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1115,8 +1115,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
--contacts-message-col-width: 420px;
|
--contacts-message-col-width: 120px;
|
||||||
--contacts-action-col-width: 172px;
|
--contacts-action-col-width: 280px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -1257,7 +1257,7 @@
|
|||||||
|
|
||||||
.contacts-list-header-count {
|
.contacts-list-header-count {
|
||||||
width: var(--contacts-message-col-width);
|
width: var(--contacts-message-col-width);
|
||||||
text-align: right;
|
text-align: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -1382,17 +1382,16 @@
|
|||||||
min-width: var(--contacts-message-col-width);
|
min-width: var(--contacts-message-col-width);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: center;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
text-align: right;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row-message-stats {
|
.row-message-stats {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: center;
|
||||||
align-items: baseline;
|
align-items: center;
|
||||||
gap: 8px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1581,6 +1580,33 @@
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row-open-chat-btn {
|
||||||
|
border: 1px solid color-mix(in srgb, var(--primary) 38%, var(--border-color));
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
background: color-mix(in srgb, var(--primary) 12%, var(--bg-secondary));
|
||||||
|
color: var(--primary);
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: color-mix(in srgb, var(--primary) 18%, var(--bg-secondary));
|
||||||
|
border-color: color-mix(in srgb, var(--primary) 55%, var(--border-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.65;
|
||||||
|
cursor: not-allowed;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
border-color: var(--border-color);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.row-detail-btn {
|
.row-detail-btn {
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -2351,8 +2377,8 @@
|
|||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
--contacts-message-col-width: 280px;
|
--contacts-message-col-width: 104px;
|
||||||
--contacts-action-col-width: 148px;
|
--contacts-action-col-width: 236px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-wrap .contacts-list-header {
|
.table-wrap .contacts-list-header {
|
||||||
|
|||||||
@@ -4047,7 +4047,7 @@ function ExportPage() {
|
|||||||
<>
|
<>
|
||||||
<div className="contacts-list-header">
|
<div className="contacts-list-header">
|
||||||
<span className="contacts-list-header-main">联系人(头像/名称/微信号)</span>
|
<span className="contacts-list-header-main">联系人(头像/名称/微信号)</span>
|
||||||
<span className="contacts-list-header-count">总消息</span>
|
<span className="contacts-list-header-count">总消息数</span>
|
||||||
<span className="contacts-list-header-actions">操作</span>
|
<span className="contacts-list-header-actions">操作</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="contacts-list" ref={contactsListRef} onScroll={onContactsListScroll}>
|
<div className="contacts-list" ref={contactsListRef} onScroll={onContactsListScroll}>
|
||||||
@@ -4091,16 +4091,25 @@ function ExportPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="row-message-count">
|
<div className="row-message-count">
|
||||||
<div className="row-message-stats">
|
<div className="row-message-stats">
|
||||||
<span className="row-message-stat total">
|
|
||||||
<span className="label">总消息</span>
|
|
||||||
<strong className={`row-message-count-value ${typeof displayedMessageCount === 'number' ? '' : 'muted'}`}>
|
<strong className={`row-message-count-value ${typeof displayedMessageCount === 'number' ? '' : 'muted'}`}>
|
||||||
{messageCountLabel}
|
{messageCountLabel}
|
||||||
</strong>
|
</strong>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row-action-cell">
|
<div className="row-action-cell">
|
||||||
<div className="row-action-main">
|
<div className="row-action-main">
|
||||||
|
<button
|
||||||
|
className="row-open-chat-btn"
|
||||||
|
disabled={!canExport}
|
||||||
|
title={canExport ? '在新窗口打开该会话' : '该联系人暂无会话记录'}
|
||||||
|
onClick={() => {
|
||||||
|
if (!canExport) return
|
||||||
|
void window.electronAPI.window.openSessionChatWindow(contact.username)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ExternalLink size={13} />
|
||||||
|
打开对话
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`row-detail-btn ${showSessionDetailPanel && sessionDetail?.wxid === contact.username ? 'active' : ''}`}
|
className={`row-detail-btn ${showSessionDetailPanel && sessionDetail?.wxid === contact.username ? 'active' : ''}`}
|
||||||
onClick={() => openSessionDetail(contact.username)}
|
onClick={() => openSessionDetail(contact.username)}
|
||||||
|
|||||||
1
src/types/electron.d.ts
vendored
1
src/types/electron.d.ts
vendored
@@ -13,6 +13,7 @@ export interface ElectronAPI {
|
|||||||
resizeToFitVideo: (videoWidth: number, videoHeight: number) => Promise<void>
|
resizeToFitVideo: (videoWidth: number, videoHeight: number) => Promise<void>
|
||||||
openImageViewerWindow: (imagePath: string, liveVideoPath?: string) => Promise<void>
|
openImageViewerWindow: (imagePath: string, liveVideoPath?: string) => Promise<void>
|
||||||
openChatHistoryWindow: (sessionId: string, messageId: number) => Promise<boolean>
|
openChatHistoryWindow: (sessionId: string, messageId: number) => Promise<boolean>
|
||||||
|
openSessionChatWindow: (sessionId: string) => Promise<boolean>
|
||||||
}
|
}
|
||||||
config: {
|
config: {
|
||||||
get: (key: string) => Promise<unknown>
|
get: (key: string) => Promise<unknown>
|
||||||
|
|||||||
Reference in New Issue
Block a user