layout mode options

This commit is contained in:
Nate Kelley 2025-08-29 19:07:16 -06:00
parent 9baba7140a
commit f4820fcc56
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
5 changed files with 36 additions and 30 deletions

View File

@ -1,11 +1,17 @@
import isEmpty from 'lodash/isEmpty';
import { useMemo } from 'react';
import type { LayoutSize } from '@/components/ui/layouts/AppLayout';
import { useIsBothMode, useIsFileMode } from './useMode';
export const useSelectedLayoutMode = () => {
const isBothMode = useIsBothMode();
const isFileMode = useIsFileMode();
export type LayoutMode = 'file-only' | 'both' | 'chat-only';
export const getDefaultLayoutMode = ({
chatId,
assetParams,
}: {
chatId: string | undefined;
assetParams: Record<string, string>;
}): LayoutMode => {
const isFileMode = isEmpty(assetParams) && !chatId;
const isBothMode = !isFileMode && !isEmpty(chatId);
if (isFileMode) {
return 'file-only' as const;
@ -18,22 +24,16 @@ export const useSelectedLayoutMode = () => {
return 'chat-only' as const;
};
export const getDefaultLayout = ({
chatId,
assetParams,
}: {
chatId: string | undefined;
assetParams: Record<string, string>;
}): LayoutSize => {
if (isEmpty(assetParams)) {
export const getDefaultLayout = ({ layout }: { layout: LayoutMode }): LayoutSize => {
if (layout === 'chat-only') {
return ['auto', '0px'];
}
if (!chatId) {
if (layout === 'file-only') {
return ['0px', 'auto'];
}
if (chatId) {
if (layout === 'both') {
return ['380px', 'auto'];
}

View File

@ -7,8 +7,8 @@ import {
type LayoutSize,
} from '@/components/ui/layouts/AppSplitter';
import { useGetCurrentMessageId, useIsStreamingMessage } from '@/context/Chats';
import type { LayoutMode } from '@/context/Chats/selected-mode-helpers';
import { useGetChatId } from '@/context/Chats/useGetChatId';
import { useSelectedLayoutMode } from '@/context/Chats/useSelectedLayoutMode';
import { useSelectedAssetId } from '../../context/BusterAssets/useSelectedAssetType';
import { ChatContainer } from './ChatContainer';
import { useAutoChatSplitter } from './ChatLayoutContext/useAutoChatSplitter';
@ -25,6 +25,7 @@ interface ChatSplitterProps {
initialLayout: LayoutSize;
autoSaveId: string;
defaultLayout: LayoutSize;
selectedLayout: LayoutMode;
}
export const ChatLayout: React.FC<ChatSplitterProps> = ({
@ -32,9 +33,9 @@ export const ChatLayout: React.FC<ChatSplitterProps> = ({
autoSaveId,
children,
defaultLayout,
selectedLayout,
}) => {
const appSplitterRef = useRef<AppSplitterRef>(null);
const selectedLayout = useSelectedLayoutMode();
const selectedAssetId = useSelectedAssetId();
const currentMessageId = useGetCurrentMessageId() || '';
const chatId = useGetChatId();
@ -54,6 +55,8 @@ export const ChatLayout: React.FC<ChatSplitterProps> = ({
useChatStreaming({ chatId, messageId: currentMessageId, isStreamingMessage });
useAutoChatSplitter({ appSplitterRef });
console.log(autoSaveId, selectedLayout, initialLayout, defaultLayout);
return (
<ClientOnly>
<AppSplitter
@ -63,7 +66,7 @@ export const ChatLayout: React.FC<ChatSplitterProps> = ({
autoSaveId={autoSaveId}
defaultLayout={defaultLayout}
allowResize={selectedLayout === 'both'}
preserveSide={'right'}
preserveSide={'left'}
leftPanelMinSize={leftPanelMinSize}
leftPanelMaxSize={leftPanelMaxSize}
rightPanelMinSize={rightPanelMinSize}

View File

@ -16,6 +16,7 @@ export const useAutoChatSplitter = ({
const layoutTrigger = selectedAssetType === 'chat' ? 'chat' : selectedAssetId;
const animateOpenSplitter = (side: 'left' | 'right' | 'both') => {
console.log('animateOpenSplitter', side);
if (appSplitterRef.current) {
const { animateWidth, getSizesInPixels } = appSplitterRef.current;
const sizes = getSizesInPixels();

View File

@ -2,19 +2,22 @@ import type { AssetType } from '@buster/server-shared/assets';
import { createFileRoute, Outlet, useLoaderData } from '@tanstack/react-router';
import omit from 'lodash/omit';
import { getAppLayout } from '@/api/server-functions/getAppLayout';
import { getDefaultLayout, getDefaultLayoutMode } from '@/context/Chats/selected-mode-helpers';
import { ChatLayout } from '@/layouts/ChatLayout';
import {
DEFAULT_CHAT_OPTION_SIDEBAR_SIZE,
DEFAULT_FILE_OPTION_SIDEBAR_SIZE,
} from '@/layouts/ChatLayout/config';
import { getDefaultLayout } from '../../../../context/Chats/useSelectedLayoutMode';
export const Route = createFileRoute('/app/_app/_asset/chats/$chatId')({
loader: async ({ params, context }) => {
const chatId = params.chatId;
const assetParams = omit(params, 'chatId');
const assetType = context.assetType;
const autoSaveId = `chat-splitter-${chatId || '🫥'}-${assetType || '❌'}`;
const autoSaveId = `chat-${chatId || '🫥'}-${assetType || '❌'}`;
const selectedLayout = getDefaultLayoutMode({
chatId,
assetParams,
});
const defaultLayout = getDefaultLayout({
layout: selectedLayout,
});
const [chatLayout, title] = await Promise.all([
getAppLayout({ data: { id: autoSaveId } }),
@ -23,10 +26,7 @@ export const Route = createFileRoute('/app/_app/_asset/chats/$chatId')({
assetType: 'chat',
}),
]);
const defaultLayout = getDefaultLayout({
chatId,
assetParams,
});
const initialLayout = chatLayout ?? defaultLayout;
return {
@ -34,6 +34,7 @@ export const Route = createFileRoute('/app/_app/_asset/chats/$chatId')({
autoSaveId,
initialLayout,
defaultLayout,
selectedLayout,
};
},
head: ({ loaderData }) => ({
@ -45,12 +46,13 @@ export const Route = createFileRoute('/app/_app/_asset/chats/$chatId')({
],
}),
component: () => {
const { initialLayout, autoSaveId, defaultLayout } = Route.useLoaderData();
const { initialLayout, selectedLayout, autoSaveId, defaultLayout } = Route.useLoaderData();
return (
<ChatLayout
initialLayout={initialLayout}
autoSaveId={autoSaveId}
defaultLayout={defaultLayout}
selectedLayout={selectedLayout}
>
<Outlet />
</ChatLayout>

View File

@ -17,7 +17,7 @@
animation-name: scrollShowAnimation;
animation-duration: 1ms; /* Firefox requires this to apply the animation */
animation-timeline: --scrollShadowContainer;
animation-range: 1px 90px; /* Start at 5px to ensure scrolling has actually occurred */
animation-range: 1px 85px; /* Start at 5px to ensure scrolling has actually occurred */
animation-fill-mode: both; /* Use 'both' instead of 'forwards' for better control */
}
}