Skip to content

Commit

Permalink
Merge pull request #398 from reorproject/merge-chat-cleanup-and-conte…
Browse files Browse the repository at this point in the history
…xt-menu

Merge chat cleanup and context menu
  • Loading branch information
joseplayero authored Sep 7, 2024
2 parents e1cc3b2 + e4a8189 commit 92c98b2
Show file tree
Hide file tree
Showing 24 changed files with 415 additions and 327 deletions.
3 changes: 2 additions & 1 deletion electron/main/electron-store/ipcHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ export const registerStoreHandlers = (store: Store<StoreSchema>, windowsManager:
return vaultChatHistories.find((chat) => chat.id === chatId)
})

ipcMain.handle('remove-chat-at-id', (event, chatID: string) => {
ipcMain.handle('delete-chat-at-id', (event, chatID: string | undefined) => {
if (!chatID) return
const vaultDir = windowsManager.getVaultDirectoryForWinContents(event.sender)

if (!vaultDir) {
Expand Down
87 changes: 2 additions & 85 deletions electron/main/electron-utils/ipcHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { app, BrowserWindow, dialog, ipcMain, Menu, MenuItem, shell } from 'electron'
import { app, ipcMain, shell } from 'electron'
import Store from 'electron-store'

import WindowsManager from '../common/windowManager'
import { StoreKeys, StoreSchema } from '../electron-store/storeConfig'
import { FileInfoNode } from '../filesystem/types'
import { ChatMetadata } from '@/contexts/ChatContext'
import { StoreSchema } from '../electron-store/storeConfig'

const registerElectronUtilsHandlers = (
store: Store<StoreSchema>,
Expand All @@ -13,87 +11,6 @@ const registerElectronUtilsHandlers = (
url: string | undefined,
indexHtml: string,
) => {
ipcMain.handle('show-context-menu-file-item', async (event, file: FileInfoNode) => {
const menu = new Menu()

menu.append(
new MenuItem({
label: 'Delete',
click: () =>
dialog
.showMessageBox({
type: 'question',
title: 'Delete File',
message: `Are you sure you want to delete "${file.name}"?`,
buttons: ['Yes', 'No'],
})
.then((confirm) => {
if (confirm.response === 0) {
event.sender.send('delete-file-listener', file.path)
}
}),
}),
)
menu.append(
new MenuItem({
label: 'Rename',
click: () => {
event.sender.send('rename-file-listener', file.path)
},
}),
)

menu.append(
new MenuItem({
label: 'Create a flashcard set',
click: () => {
event.sender.send('create-flashcard-file-listener', file.path)
},
}),
)

menu.append(
new MenuItem({
label: 'Add file to chat context',
click: () => {
event.sender.send('add-file-to-chat-listener', file.path)
},
}),
)

const browserWindow = BrowserWindow.fromWebContents(event.sender)
if (browserWindow) {
menu.popup({ window: browserWindow })
}
})

ipcMain.handle('show-chat-menu-item', (event, chatRow: ChatMetadata) => {
const menu = new Menu()

menu.append(
new MenuItem({
label: 'Delete Chat',
click: () => {
const vaultDir = windowsManager.getVaultDirectoryForWinContents(event.sender)

if (!vaultDir) {
return
}

const chatHistoriesMap = store.get(StoreKeys.ChatHistories)
const allChatHistories = chatHistoriesMap[vaultDir] || []
const filteredChatHistories = allChatHistories.filter((item) => item.id !== chatRow.id)
chatHistoriesMap[vaultDir] = filteredChatHistories
store.set(StoreKeys.ChatHistories, chatHistoriesMap)
event.sender.send('update-chat-histories', chatHistoriesMap[vaultDir] || [])
},
}),
)

const browserWindow = BrowserWindow.fromWebContents(event.sender)
if (browserWindow) menu.popup({ window: browserWindow })
})

ipcMain.handle('open-external', (event, _url) => {
shell.openExternal(_url)
})
Expand Down
7 changes: 2 additions & 5 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import {
LLMGenerationParameters,
Tab,
} from 'electron/main/electron-store/storeConfig'
import { FileInfoNode, FileInfoTree, RenameFileProps, WriteFileProps } from 'electron/main/filesystem/types'
import { FileInfoTree, RenameFileProps, WriteFileProps } from 'electron/main/filesystem/types'
import { DBEntry, DBQueryResult } from 'electron/main/vector-database/schema'

import { Chat } from '@/components/Chat/types'
import { ChatMetadata } from '@/contexts/ChatContext'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type IPCHandler<T extends (...args: any[]) => any> = (...args: Parameters<T>) => Promise<ReturnType<T>>
Expand Down Expand Up @@ -40,8 +39,6 @@ const electronUtils = {
getPlatform: createIPCHandler<() => Promise<string>>('get-platform'),
openNewWindow: createIPCHandler<() => Promise<void>>('open-new-window'),
getReorAppVersion: createIPCHandler<() => Promise<string>>('get-reor-app-version'),
showFileItemContextMenu: createIPCHandler<(file: FileInfoNode) => Promise<void>>('show-context-menu-file-item'),
showChatItemContext: createIPCHandler<(chatRow: ChatMetadata) => Promise<void>>('show-chat-menu-item'),
}

const electronStore = {
Expand Down Expand Up @@ -73,7 +70,7 @@ const electronStore = {
setHasUserOpenedAppBefore: createIPCHandler<() => Promise<void>>('set-user-has-opened-app-before'),
getAllChats: createIPCHandler<() => Promise<Chat[]>>('get-all-chats'),
updateChat: createIPCHandler<(chat: Chat) => Promise<void>>('update-chat'),
removeChatAtID: createIPCHandler<(chatID: string) => Promise<void>>('remove-chat-at-id'),
deleteChatAtID: createIPCHandler<(chatID: string) => Promise<void>>('delete-chat-at-id'),
getChat: createIPCHandler<(chatID: string) => Promise<Chat>>('get-chat'),
getSBCompact: createIPCHandler<() => Promise<boolean>>('get-sb-compact'),
setSBCompact: createIPCHandler<(isSBCompact: boolean) => Promise<void>>('set-sb-compact'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,24 @@ export interface ChatItemProps {

export const ChatItem: React.FC<ChatItemProps> = ({ chatMetadata }) => {
const { currentOpenChat } = useChatContext()
const { openContent: openTabContent } = useWindowContentContext()
const { openContent, showContextMenu } = useWindowContentContext()

const itemClasses = `
flex items-center cursor-pointer py-2 px-3 rounded-md
transition-colors duration-150 ease-in-out
${chatMetadata.id === currentOpenChat?.id ? 'bg-neutral-700 text-white' : 'text-gray-300 hover:bg-neutral-800'}
`

const handleContextMenu = (e: React.MouseEvent) => {
e.preventDefault()
window.electronUtils.showChatItemContext(chatMetadata)
}

return (
<div>
<div
onClick={async () => {
openTabContent(chatMetadata.id)
openContent(chatMetadata.id)
}}
className={itemClasses}
onContextMenu={handleContextMenu}
onContextMenu={(e) => {
e.stopPropagation()
showContextMenu(e, 'ChatItem', { chatMetadata })
}}
>
<IoChatbubbles />
<span className="ml-2 flex-1 truncate text-[11px] font-medium">{chatMetadata.displayName}</span>
Expand All @@ -40,21 +38,21 @@ export const ChatItem: React.FC<ChatItemProps> = ({ chatMetadata }) => {
)
}

export const ChatsSidebar: React.FC = () => {
export const ChatSidebar: React.FC = () => {
const [isRecentsOpen, setIsRecentsOpen] = useState(true)
const dropdownAnimationDelay = 0.2
const dropdownAnimationDelay = 0.02

const { setShowChatbot, allChatsMetadata, setCurrentOpenChat } = useChatContext()

const toggleRecents = () => setIsRecentsOpen((prev) => !prev)

const currentSelectedChatID = useRef<string | undefined>()

useEffect(() => {
const deleteChatRow = window.ipcRenderer.receive('remove-chat-at-id', (chatID) => {
const deleteChatRow = window.ipcRenderer.receive('delete-chat-at-id', (chatID) => {
if (chatID === currentSelectedChatID.current) {
setShowChatbot(false)
}
window.electronStore.removeChatAtID(chatID)
window.electronStore.deleteChatAtID(chatID)
})

return () => {
Expand Down
51 changes: 51 additions & 0 deletions src/components/Common/CommonModals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react'

import NewNoteComponent from '../File/NewNote'
import { useModalOpeners } from '@/contexts/ModalContext'
import NewDirectoryComponent from '../File/NewDirectory'
import SettingsModal from '../Settings/Settings'
import FlashcardMenuModal from '../Flashcard/FlashcardMenuModal'
import { useFileContext } from '@/contexts/FileContext'
import RenameNoteModal from '../File/RenameNote'
import RenameDirModal from '../File/RenameDirectory'

const CommonModals: React.FC = () => {
const {
isNewNoteModalOpen,
setIsNewNoteModalOpen,
isNewDirectoryModalOpen,
setIsNewDirectoryModalOpen,
isSettingsModalOpen,
setIsSettingsModalOpen,
isFlashcardModeOpen,
setIsFlashcardModeOpen,
initialFileToCreateFlashcard,
setInitialFileToCreateFlashcard,
initialFileToReviewFlashcard,
setInitialFileToReviewFlashcard,
} = useModalOpeners()

const { noteToBeRenamed, fileDirToBeRenamed } = useFileContext()

return (
<div>
<NewNoteComponent isOpen={isNewNoteModalOpen} onClose={() => setIsNewNoteModalOpen(false)} />
<NewDirectoryComponent isOpen={isNewDirectoryModalOpen} onClose={() => setIsNewDirectoryModalOpen(false)} />
{noteToBeRenamed && <RenameNoteModal />}
{fileDirToBeRenamed && <RenameDirModal />}
<SettingsModal isOpen={isSettingsModalOpen} onClose={() => setIsSettingsModalOpen(false)} />
<FlashcardMenuModal
isOpen={isFlashcardModeOpen}
onClose={() => {
setIsFlashcardModeOpen(false)
setInitialFileToCreateFlashcard('')
setInitialFileToReviewFlashcard('')
}}
initialFileToCreateFlashcard={initialFileToCreateFlashcard}
initialFileToReviewFlashcard={initialFileToReviewFlashcard}
/>
</div>
)
}

export default CommonModals
7 changes: 1 addition & 6 deletions src/components/Common/EmptyPage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React from 'react'
import { ImFileEmpty } from 'react-icons/im'
import { useModalOpeners } from '../../contexts/ModalContext'
import NewNoteComponent from '../File/NewNote'
import NewDirectoryComponent from '../File/NewDirectory'

const EmptyPage: React.FC = () => {
const { isNewNoteModalOpen, setIsNewNoteModalOpen, isNewDirectoryModalOpen, setIsNewDirectoryModalOpen } =
useModalOpeners()
const { setIsNewNoteModalOpen, setIsNewDirectoryModalOpen } = useModalOpeners()

return (
<div className="absolute flex size-full flex-col items-center justify-center overflow-hidden pb-40 text-white">
Expand All @@ -31,8 +28,6 @@ const EmptyPage: React.FC = () => {
Create a Folder
</button>
</div>
<NewNoteComponent isOpen={isNewNoteModalOpen} onClose={() => setIsNewNoteModalOpen(false)} />
<NewDirectoryComponent isOpen={isNewDirectoryModalOpen} onClose={() => setIsNewDirectoryModalOpen(false)} />
</div>
)
}
Expand Down
Loading

0 comments on commit 92c98b2

Please sign in to comment.