Skip to content

Commit

Permalink
Merge pull request #46 from Royal-lobster/remove-messages
Browse files Browse the repository at this point in the history
Adds Remove Messages and adds setting page improvements
  • Loading branch information
Royal-lobster authored Nov 26, 2023
2 parents 4b4fa35 + f074862 commit ccc5a8e
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 50 deletions.
8 changes: 8 additions & 0 deletions .changeset/quick-donuts-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"syncia": minor
---

- adds ability to remove messages
- makes screenshots to show all with object fit contain
- fixed model names showing numbers
- make open ai key show and hide and hide by default
Binary file modified artifacts/chrome.zip
Binary file not shown.
58 changes: 43 additions & 15 deletions src/components/Settings/Sections/ChatSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import FieldWrapper from '../Elements/FieldWrapper'
import { useSettings } from '../../../hooks/useSettings'
import { validateApiKey } from '../../../lib/validApiKey'
import { AvailableModels, Mode } from '../../../config/settings'
import { capitalizeText } from '../../../lib/capitalizeText'
import { useState } from 'react'
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'

const ChatSettings = () => {
const [settings, setSettings] = useSettings()
const [showPassword, setShowPassword] = useState(false)

const chatSettings = settings.chat

const apiKeyInputRef = React.useRef<HTMLInputElement>(null)
Expand Down Expand Up @@ -81,14 +86,29 @@ const ChatSettings = () => {
onSubmit={handleOpenAiKeySubmit}
>
<div className="cdx-flex cdx-gap-2 cdx-items-center">
<input
required
pattern="sk-[a-zA-Z0-9]{48}"
className="input"
ref={apiKeyInputRef}
placeholder="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
defaultValue={chatSettings.openAIKey || ''}
/>
<div className="cdx-relative cdx-w-full">
<input
required
pattern="sk-[a-zA-Z0-9]{48}"
ref={apiKeyInputRef}
placeholder="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
defaultValue={chatSettings.openAIKey || ''}
type={showPassword ? 'text' : 'password'}
className="input"
/>

<button
type="button"
className="cdx-absolute cdx-right-4 cdx-top-1/2 cdx-transform cdx--translate-y-1/2 cdx-text-neutral-500 dark:cdx-text-neutral-200 cdx-bg-transparent cdx-outline-none cdx-cursor-pointer"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? (
<AiOutlineEyeInvisible size={18} />
) : (
<AiOutlineEye size={18} />
)}
</button>
</div>
<button type="submit" className="btn">
Update
</button>
Expand All @@ -109,9 +129,15 @@ const ChatSettings = () => {
className="input cdx-w-44"
onChange={handleModalChange}
>
{Object.values(AvailableModels).map((modal) => (
{Object.keys(AvailableModels).map((modal) => (
<option key={modal} value={modal}>
{modal}
{capitalizeText(
modal
.toLowerCase()
.replace('gpt', 'GPT')
.replace('3_5', '3.5')
.replaceAll('_', ' '),
)}
</option>
))}
</select>
Expand All @@ -131,11 +157,13 @@ const ChatSettings = () => {
onChange={handleModeChange}
className="input cdx-w-36"
>
{Object.entries(Mode).map(([mode, value]) => (
<option key={value} value={value}>
{mode.replace('_', ' ').toLowerCase()}
</option>
))}
{Object.keys(Mode)
.filter((v) => Number.isNaN(Number(v)))
.map((value) => (
<option key={value} value={value}>
{capitalizeText(value.replace('_', ' ').toLowerCase())}
</option>
))}
</select>
</FieldWrapper>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/Settings/Sections/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import FieldWrapper from '../Elements/FieldWrapper'
import { useSettings } from '../../../hooks/useSettings'
import { ThemeOptions } from '../../../config/settings'
import * as Switch from '@radix-ui/react-switch'
import { capitalizeText } from '../../../lib/capitalizeText'

const GeneralSettings = () => {
const [settings, setSettings] = useSettings()
Expand Down Expand Up @@ -36,7 +37,7 @@ const GeneralSettings = () => {
>
{Object.values(ThemeOptions).map((theme) => (
<option key={theme} value={theme}>
{theme}
{capitalizeText(theme)}
</option>
))}
</select>
Expand Down
19 changes: 15 additions & 4 deletions src/components/Sidebar/chat/ChatList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import remarkBreaks from 'remark-breaks'
import rehypeRaw from 'rehype-raw'
import { ChatMessage, ChatRole } from '../../../hooks/useCurrentChat'
import FilePreviewBar from './FilePreviewBar'
import { RiCloseLine } from 'react-icons/ri'

interface ChatListProps {
messages: ChatMessage[]
removeMessagePair: (timestamp: number) => void
}

const ChatList = ({ messages }: ChatListProps) => {
const ChatList = ({ messages, removeMessagePair }: ChatListProps) => {
const containerRef = useRef<HTMLDivElement>(null)

useEffect(() => {
Expand All @@ -37,10 +39,10 @@ const ChatList = ({ messages }: ChatListProps) => {
height={300}
width={300}
/>
<h1 className="cdx-text-xl cdx-text-gray-500">
<h1 className="cdx-text-xl cdx-text-gray-500 dark:cdx-text-gray-400">
Start a new conversation 🎉
</h1>
<p className="cdx-text-gray-500 cdx-mt-1 cdx-leading-tight cdx-font-light">
<p className="cdx-text-gray-500 dark:cdx-text-gray-400 cdx-mt-1 cdx-leading-tight cdx-font-light">
Type your message at the bottom <br /> and press send button
</p>
</div>
Expand All @@ -50,9 +52,18 @@ const ChatList = ({ messages }: ChatListProps) => {
.map((msg, i) => (
<div
data-user={msg.role === ChatRole.USER ? 'true' : undefined}
className="markdown cdx-px-4 cdx-py-2 data-[user]:cdx-border-l-2 cdx-border-blue-400 data-[user]:cdx-bg-black/5 data-[user]:dark:cdx-bg-neutral-900/50 cdx-max-w-[400px]"
className="markdown cdx-group cdx-relative cdx-px-4 cdx-py-2 data-[user]:cdx-border-l-2 cdx-border-blue-400 data-[user]:cdx-bg-black/5 data-[user]:dark:cdx-bg-neutral-900/50 cdx-max-w-[400px]"
key={`${msg.timestamp}-${i}`}
>
{msg.role === ChatRole.USER && (
<button
type="button"
onClick={() => removeMessagePair(msg.timestamp)}
className="cdx-absolute group-hover:cdx-visible cdx-invisible cdx-right-2 cdx-top-2 cdx-p-0.5 cdx-bg-black/20 cdx-rounded"
>
<RiCloseLine />
</button>
)}
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkBreaks]}
rehypePlugins={[rehypeRaw]}
Expand Down
47 changes: 28 additions & 19 deletions src/components/Sidebar/chat/FilePreviewBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,37 @@ interface FilePreviewBarProps {

const FilePreviewBar = ({ files, removeFile }: FilePreviewBarProps) => {
if (files.length === 0) return null

return (
<div className="cdx-flex cdx-gap-2 cdx-m-2">
{files.map((file) => (
<div key={file.id} className="cdx-flex cdx-relative">
<div className="cdx-flex-grow">
<img
src={URL.createObjectURL(file.blob)}
alt="preview"
className="cdx-w-14 cdx-h-14 cdx-object-cover cdx-rounded cdx-bg-neutral-500"
/>
</div>
{removeFile && (
<button
onClick={() => removeFile(file.id)}
type="button"
className="cdx-absolute cdx-top-0.5 cdx-right-0.5 cdx-bg-black/30 cdx-rounded-full cdx-text-neutral-500 dark:cdx-text-neutral-200 cdx-ml-2"
{files.map((file) => {
const imageUrl = URL.createObjectURL(file.blob)
return (
<div key={file.id} className="cdx-flex cdx-relative">
<a
href={imageUrl}
target="_blank"
rel="noopener noreferrer"
className="cdx-block cdx-flex-grow"
>
<RiCloseLine size={16} />
</button>
)}
</div>
))}
<img
src={imageUrl}
alt="preview"
className="cdx-w-14 cdx-h-14 cdx-object-contain cdx-rounded dark:cdx-bg-neutral-800 cdx-bg-neutral-400"
/>
</a>
{removeFile && (
<button
onClick={() => removeFile(file.id)}
type="button"
className="cdx-absolute cdx-top-0.5 cdx-right-0.5 cdx-bg-black/30 cdx-rounded-full cdx-text-neutral-500 dark:cdx-text-neutral-200 cdx-ml-2"
>
<RiCloseLine size={16} />
</button>
)}
</div>
)
})}
</div>
)
}
Expand Down
22 changes: 14 additions & 8 deletions src/components/Sidebar/chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,19 @@ interface ChatProps {
}

const Chat = ({ settings }: ChatProps) => {
const { messages, submitQuery, clearMessages, generating, cancelRequest } =
useChatCompletion({
model: settings.chat.modal,
apiKey: settings.chat.openAIKey!,
mode: settings.chat.mode,
systemPrompt: SYSTEM_PROMPT,
})
const {
messages,
submitQuery,
clearMessages,
generating,
cancelRequest,
removeMessagePair,
} = useChatCompletion({
model: settings.chat.modal,
apiKey: settings.chat.openAIKey!,
mode: settings.chat.mode,
systemPrompt: SYSTEM_PROMPT,
})

useEffect(() => {
const handleWindowMessage = (event: MessageEvent) => {
Expand All @@ -37,7 +43,7 @@ const Chat = ({ settings }: ChatProps) => {

return (
<>
<ChatList messages={messages} />
<ChatList messages={messages} removeMessagePair={removeMessagePair} />
<SidebarInput
loading={generating}
submitMessage={submitQuery}
Expand Down
2 changes: 1 addition & 1 deletion src/config/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const defaultSettings: Settings = {
},
chat: {
openAIKey: null,
modal: AvailableModels.GPT_3_5_TURBO,
modal: AvailableModels.GPT_4_VISION,
mode: Mode.BALANCED,
},
general: {
Expand Down
10 changes: 9 additions & 1 deletion src/hooks/useChatCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const useChatCompletion = ({
addNewMessage,
commitToStoredMessages,
clearMessages,
removeMessagePair,
} = useCurrentChat()
const [generating, setGenerating] = useState(false)

Expand Down Expand Up @@ -124,5 +125,12 @@ export const useChatCompletion = ({
setGenerating(false)
}

return { messages, submitQuery, generating, cancelRequest, clearMessages }
return {
messages,
submitQuery,
generating,
cancelRequest,
clearMessages,
removeMessagePair,
}
}
11 changes: 11 additions & 0 deletions src/hooks/useCurrentChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ export const useCurrentChat = () => {
setMessages((m) => [...m, newMessage])
}

const removeMessagePair = (timestamp: number) => {
setMessages((p) => {
const index = p.findIndex((msg) => msg.timestamp === timestamp)
if (index === -1 || p[index].role !== ChatRole.USER) return p
p.splice(index, 2) // remove the user message and the assistant message
return [...p]
})
commitToStoredMessages()
}

const commitToStoredMessages = async () => {
if (!currentChatIdRef.current) return
setStorage(getStoredChatKey(currentChatIdRef.current), messagesRef.current)
Expand All @@ -152,5 +162,6 @@ export const useCurrentChat = () => {
commitToStoredMessages,
clearMessages,
currentChatId,
removeMessagePair,
}
}
6 changes: 6 additions & 0 deletions src/lib/capitalizeText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const capitalizeText = (text: string): string => {
return text
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
}
6 changes: 5 additions & 1 deletion src/lib/getScreenshotImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import html2canvas from 'html2canvas'
* 2. Grab the screen image with canvas
* 3. Crop the image with the user's selection
* 4. Return the cropped image as a blob
*
* TODO: This approach is not ideal as the website visible to user may not be the same as the one
* captured by html2canvas. For example, if the user has adblock installed, the website may look
* different to the one captured by html2canvas. We should consider another approach to capture
*/
export const getScreenshotImage = async (): Promise<Blob> => {
// Create a snipping tool view for the user to select the area of the screen
Expand All @@ -21,7 +25,7 @@ export const getScreenshotImage = async (): Promise<Blob> => {

const snipeSelection: HTMLDivElement = document.createElement('div')
snipeSelection.style.position = 'fixed'
snipeSelection.style.border = '1px solid #fff'
snipeSelection.style.border = '1px solid #ffffff2a'
snipeSelection.style.backgroundColor = 'rgba(255, 255, 255, 0.1)'
snipeSelection.style.zIndex = '2147483647' // Maximum z-index

Expand Down

0 comments on commit ccc5a8e

Please sign in to comment.