Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add chat width setting option for thread #4278

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/containers/Layout/TopPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const TopPanel = () => {
theme="icon"
onClick={() => {
setMainViewState(MainViewState.Settings)
setSelectedSetting('Appearance')
setSelectedSetting('Preferences')
}}
>
<PaletteIcon size={16} className="cursor-pointer" />
Expand Down
7 changes: 7 additions & 0 deletions web/helpers/atoms/Setting.atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const PRODUCT_ANALYTIC_PROMPT = 'productAnalyticPrompt'
export const THEME_DATA = 'themeData'
export const THEME_OPTIONS = 'themeOptions'
export const THEME_PATH = 'themePath'
export const CHAT_WIDTH = 'chatWidth'
export const themesOptionsAtom = atomWithStorage<
{ name: string; value: string }[]
>(THEME_OPTIONS, [], undefined, { getOnInit: true })
Expand Down Expand Up @@ -61,3 +62,9 @@ export const productAnalyticPromptAtom = atomWithStorage<boolean>(
undefined,
{ getOnInit: true }
)
export const chatWidthAtom = atomWithStorage<string>(
CHAT_WIDTH,
'full',
undefined,
{ getOnInit: true }
)
Binary file added web/public/images/compact-width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added web/public/images/full-width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions web/screens/Settings/Appearance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Button, Select, Switch } from '@janhq/joi'
import { useAtom, useAtomValue } from 'jotai'

import {
chatWidthAtom,
janThemesPathAtom,
reduceTransparentAtom,
selectedThemeIdAtom,
Expand All @@ -25,6 +26,16 @@ export default function AppearanceOptions() {
reduceTransparentAtom
)
const [spellCheck, setSpellCheck] = useAtom(spellCheckAtom)
const [chatWidth, setChatWidth] = useAtom(chatWidthAtom)

const chatWidthOption = [
{ name: 'Full Width', value: 'full', img: 'images/full-width.png' },
{
name: 'Compact Width',
value: 'compact',
img: 'images/compact-width.png',
},
]

const handleClickTheme = useCallback(
async (e: string) => {
Expand Down Expand Up @@ -91,6 +102,54 @@ export default function AppearanceOptions() {
</div>
</div>
)}
<div className="flex w-full flex-col items-start justify-between gap-4 border-b border-[hsla(var(--app-border))] py-4 first:pt-0 last:border-none sm:flex-row">
<div className="w-full space-y-1 lg:w-3/4">
<div className="flex gap-x-2">
<h6 className="font-semibold capitalize">Chat Width</h6>
</div>
<p className=" font-medium leading-relaxed text-[hsla(var(--text-secondary))]">
Choose the width of the chat area to customize your conversation
view
</p>
</div>
<div className="flex-shrink-0">
<div className="flex items-center gap-4">
{chatWidthOption.map((option) => {
return (
<div
className="inline-flex flex-col items-center justify-center text-center"
key={option.name}
>
<label
className="relative cursor-pointer"
htmlFor={option.name}
>
<img
src={option.img}
alt={option.value}
width={140}
className="rounded-lg"
/>
<p className="my-2 font-medium">{option.name}</p>
<div className="relative">
<input
name="chatWidth"
value={option.value}
checked={chatWidth === option.value}
onChange={() => setChatWidth(option.value)}
type="radio"
className="peer h-5 w-5 cursor-pointer appearance-none rounded-full border border-[hsla(var(--app-border))] transition-all checked:border-[hsla(var(--primary-bg))]"
id={option.name}
/>
<span className="absolute left-1/2 top-1/2 -mt-[3px] h-3 w-3 -translate-x-1/2 -translate-y-1/2 transform rounded-full bg-[hsla(var(--primary-bg))] opacity-0 transition-opacity duration-200 peer-checked:opacity-100"></span>
</div>
</label>
</div>
)
})}
</div>
</div>
</div>
<div className="flex w-full flex-col items-start justify-between gap-4 border-b border-[hsla(var(--app-border))] py-4 first:pt-0 last:border-none sm:flex-row">
<div className="w-full space-y-1 lg:w-3/4">
<div className="flex gap-x-2">
Expand Down
2 changes: 1 addition & 1 deletion web/screens/Settings/SettingDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const SettingDetail = () => {
case 'Extensions':
return <ExtensionCatalog />

case 'Appearance':
case 'Preferences':
return <AppearanceOptions />

case 'Keyboard Shortcuts':
Expand Down
2 changes: 1 addition & 1 deletion web/screens/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { selectedSettingAtom } from '@/helpers/atoms/Setting.atom'

export const SettingScreenList = [
'My Models',
'Appearance',
'Preferences',
'Keyboard Shortcuts',
'Privacy',
'Advanced Settings',
Expand Down
10 changes: 9 additions & 1 deletion web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,39 @@
tokenSpeedAtom,
} from '@/helpers/atoms/ChatMessage.atom'

import { chatWidthAtom } from '@/helpers/atoms/Setting.atom'

const MessageContainer: React.FC<
ThreadMessage & { isCurrentMessage: boolean }
> = (props) => {
const isUser = props.role === ChatCompletionRole.User
const isSystem = props.role === ChatCompletionRole.System
const editMessage = useAtomValue(editMessageAtom)
const activeAssistant = useAtomValue(activeAssistantAtom)
const tokenSpeed = useAtomValue(tokenSpeedAtom)
const chatWidth = useAtomValue(chatWidthAtom)

Check warning on line 36 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

31-36 lines are not covered with tests

const text = useMemo(

Check warning on line 38 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

38 line is not covered with tests
() =>
props.content.find((e) => e.type === ContentType.Text)?.text?.value ?? '',

Check warning on line 40 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

40 line is not covered with tests
[props.content]
)

const image = useMemo(

Check warning on line 44 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

44 line is not covered with tests
() =>
props.content.find((e) => e.type === ContentType.Image)?.image_url?.url,

Check warning on line 46 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

46 line is not covered with tests
[props.content]
)

const attachedFile = useMemo(() => 'attachments' in props, [props])

Check warning on line 50 in web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

50 line is not covered with tests

return (
<div className="group relative mx-auto max-w-[700px] p-4">
<div
className={twMerge(
'group relative mx-auto p-4',
chatWidth === 'compact' && 'max-w-[700px]'
)}
>
<div
className={twMerge(
'mb-2 flex items-center justify-start gap-x-2',
Expand Down
Loading