From da2f97c227266e18786ef19b17f0d521751cf28d Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Mon, 16 Jun 2025 15:02:43 +0700 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8enhancement:=20add=20setting=20chat=20?= =?UTF-8?q?width=20container=20(#5289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨enhancement: add setting conversation width * ✨enahncement: cleanup log and change improve accesibility * ✨enahcement: move const beta version --- web-app/src/components/ui/skeleton.tsx | 13 ++ web-app/src/containers/ChatInput.tsx | 19 +-- web-app/src/containers/ChatWidthSwitcher.tsx | 61 +++++++ web-app/src/containers/ThreadContent.tsx | 159 +++++++++--------- .../src/containers/TokenSpeedIndicator.tsx | 19 ++- web-app/src/containers/dialogs/AppUpdater.tsx | 2 +- web-app/src/hooks/useAppearance.ts | 8 + web-app/src/routes/settings/appearance.tsx | 10 ++ web-app/src/routes/threads/$threadId.tsx | 16 +- 9 files changed, 202 insertions(+), 105 deletions(-) create mode 100644 web-app/src/components/ui/skeleton.tsx create mode 100644 web-app/src/containers/ChatWidthSwitcher.tsx diff --git a/web-app/src/components/ui/skeleton.tsx b/web-app/src/components/ui/skeleton.tsx new file mode 100644 index 000000000..9efe5678e --- /dev/null +++ b/web-app/src/components/ui/skeleton.tsx @@ -0,0 +1,13 @@ +import { cn } from '@/lib/utils' + +function Skeleton({ className, ...props }: React.ComponentProps<'div'>) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/web-app/src/containers/ChatInput.tsx b/web-app/src/containers/ChatInput.tsx index a83adc59e..7737652eb 100644 --- a/web-app/src/containers/ChatInput.tsx +++ b/web-app/src/containers/ChatInput.tsx @@ -21,7 +21,6 @@ import { IconTool, IconCodeCircle2, IconPlayerStopFilled, - IconBrandSpeedtest, IconX, } from '@tabler/icons-react' import { useTranslation } from 'react-i18next' @@ -45,12 +44,7 @@ type ChatInputProps = { initialMessage?: boolean } -const ChatInput = ({ - model, - className, - showSpeedToken = true, - initialMessage, -}: ChatInputProps) => { +const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => { const textareaRef = useRef(null) const [isFocused, setIsFocused] = useState(false) const [rows, setRows] = useState(1) @@ -60,7 +54,7 @@ const ChatInput = ({ const { currentThreadId } = useThreads() const { t } = useTranslation() const { spellCheckChatInput } = useGeneralSetting() - const { tokenSpeed } = useAppState() + const { showModal, PromiseModal: OutOfContextModal } = useOutOfContextPromiseModal() const maxRows = 10 @@ -559,15 +553,6 @@ const ChatInput = ({ )}
- - {showSpeedToken && ( -
- - - {Math.round(tokenSpeed?.tokenSpeed ?? 0)} tokens/sec - -
- )} {streamingContent ? ( diff --git a/web-app/src/containers/ChatWidthSwitcher.tsx b/web-app/src/containers/ChatWidthSwitcher.tsx new file mode 100644 index 000000000..ddaf4d4fe --- /dev/null +++ b/web-app/src/containers/ChatWidthSwitcher.tsx @@ -0,0 +1,61 @@ +import { Skeleton } from '@/components/ui/skeleton' +import { useAppearance } from '@/hooks/useAppearance' +import { cn } from '@/lib/utils' +import { IconCircleCheckFilled } from '@tabler/icons-react' + +export function ChatWidthSwitcher() { + const { chatWidth, setChatWidth } = useAppearance() + + return ( +
+ + +
+ ) +} diff --git a/web-app/src/containers/ThreadContent.tsx b/web-app/src/containers/ThreadContent.tsx index 66205248a..af359d32e 100644 --- a/web-app/src/containers/ThreadContent.tsx +++ b/web-app/src/containers/ThreadContent.tsx @@ -359,97 +359,98 @@ export const ThreadContent = memo( {!isToolCalls && (
-
- - - - - - -

Delete

-
-
- - - - -
- -
-
- -

Metadata

-
-
-
- - - Message Metadata -
-
- -
-
- - - - - -
-
-
- - {item.isLastMessage && ( +
+
+ -

Regenerate

+

Delete

- )} + + + + +
+ +
+
+ +

Metadata

+
+
+
+ + + Message Metadata +
+
+ +
+
+ + + + + +
+
+
+ + {item.isLastMessage && ( + + + + + +

Regenerate

+
+
+ )} +
diff --git a/web-app/src/containers/TokenSpeedIndicator.tsx b/web-app/src/containers/TokenSpeedIndicator.tsx index b1dfb841c..5309d890c 100644 --- a/web-app/src/containers/TokenSpeedIndicator.tsx +++ b/web-app/src/containers/TokenSpeedIndicator.tsx @@ -1,19 +1,28 @@ -import { IconBrandSpeedtest } from '@tabler/icons-react' +import { useAppState } from '@/hooks/useAppState' +import { Gauge } from 'lucide-react' interface TokenSpeedIndicatorProps { metadata?: Record + streaming?: boolean } export const TokenSpeedIndicator = ({ - metadata + metadata, + streaming, }: TokenSpeedIndicatorProps) => { - const persistedTokenSpeed = (metadata?.tokenSpeed as { tokenSpeed: number })?.tokenSpeed + const { tokenSpeed } = useAppState() + const persistedTokenSpeed = (metadata?.tokenSpeed as { tokenSpeed: number }) + ?.tokenSpeed return (
- + + - {Math.round(persistedTokenSpeed)} tokens/sec + {Math.round( + streaming ? Number(tokenSpeed?.tokenSpeed) : persistedTokenSpeed + )} +  tokens/sec
) diff --git a/web-app/src/containers/dialogs/AppUpdater.tsx b/web-app/src/containers/dialogs/AppUpdater.tsx index 02a84accb..a17876a15 100644 --- a/web-app/src/containers/dialogs/AppUpdater.tsx +++ b/web-app/src/containers/dialogs/AppUpdater.tsx @@ -22,8 +22,8 @@ const DialogAppUpdater = () => { setRemindMeLater(true) } - const beta = VERSION.includes('beta') const nightly = VERSION.includes('-') + const beta = VERSION.includes('beta') const { release, fetchLatestRelease } = useReleaseNotes() diff --git a/web-app/src/hooks/useAppearance.ts b/web-app/src/hooks/useAppearance.ts index 60340e542..51a1ce10e 100644 --- a/web-app/src/hooks/useAppearance.ts +++ b/web-app/src/hooks/useAppearance.ts @@ -6,8 +6,10 @@ import { rgb, oklch, formatCss } from 'culori' import { useTheme } from './useTheme' export type FontSize = '14px' | '15px' | '16px' | '18px' +export type ChatWidth = 'full' | 'compact' interface AppearanceState { + chatWidth: ChatWidth fontSize: FontSize appBgColor: RgbaColor appMainViewBgColor: RgbaColor @@ -19,6 +21,7 @@ interface AppearanceState { appAccentTextColor: string appDestructiveTextColor: string appLeftPanelTextColor: string + setChatWidth: (size: ChatWidth) => void setFontSize: (size: FontSize) => void setAppBgColor: (color: RgbaColor) => void setAppMainViewBgColor: (color: RgbaColor) => void @@ -129,6 +132,7 @@ export const useAppearance = create()( persist( (set) => { return { + chatWidth: 'compact', fontSize: defaultFontSize, appBgColor: defaultAppBgColor, appMainViewBgColor: defaultAppMainViewBgColor, @@ -270,6 +274,10 @@ export const useAppearance = create()( }) }, + setChatWidth: (value: ChatWidth) => { + set({ chatWidth: value }) + }, + setFontSize: (size: FontSize) => { // Update CSS variable document.documentElement.style.setProperty('--font-size-base', size) diff --git a/web-app/src/routes/settings/appearance.tsx b/web-app/src/routes/settings/appearance.tsx index d59abb9b3..21b99c73e 100644 --- a/web-app/src/routes/settings/appearance.tsx +++ b/web-app/src/routes/settings/appearance.tsx @@ -18,6 +18,7 @@ import CodeBlockStyleSwitcher from '@/containers/CodeBlockStyleSwitcher' import { LineNumbersSwitcher } from '@/containers/LineNumbersSwitcher' import { CodeBlockExample } from '@/containers/CodeBlockExample' import { toast } from 'sonner' +import { ChatWidthSwitcher } from '@/containers/ChatWidthSwitcher' // eslint-disable-next-line @typescript-eslint/no-explicit-any export const Route = createFileRoute(route.settings.appearance as any)({ @@ -98,6 +99,15 @@ function Appareances() { /> + {/* Chat Message */} + + + + + {/* Codeblock */} ({ @@ -213,7 +213,12 @@ function ThreadDetail() { 'flex flex-col h-full w-full overflow-auto px-4 pt-4 pb-3' )} > -
+
{messages && messages.map((item, index) => { // Only pass isLastMessage to the last message in the array @@ -247,7 +252,12 @@ function ThreadDetail() {
-
+