chore: test deploy snapshot
This commit is contained in:
@@ -40,6 +40,7 @@ type PendingChatRequest = {
|
||||
};
|
||||
|
||||
type PendingContextConfirm = {
|
||||
requestId?: string;
|
||||
sessionId: string;
|
||||
mode: 'queue' | 'direct';
|
||||
text: string;
|
||||
@@ -374,6 +375,7 @@ export function useConversationComposerController({
|
||||
const executeSendMessage = useCallback(
|
||||
async (request: PendingContextConfirm) => {
|
||||
const {
|
||||
requestId: requestedRequestId,
|
||||
sessionId,
|
||||
mode,
|
||||
text,
|
||||
@@ -490,7 +492,7 @@ export function useConversationComposerController({
|
||||
return false;
|
||||
}
|
||||
|
||||
const requestId = createClientRequestId();
|
||||
const requestId = requestedRequestId?.trim() || createClientRequestId();
|
||||
const outgoingRequest: PendingChatRequest = {
|
||||
sessionId: targetSessionId,
|
||||
requestId,
|
||||
@@ -535,6 +537,7 @@ export function useConversationComposerController({
|
||||
chatTypeLabel: requestChatTypeLabel,
|
||||
requestOrigin: origin ?? 'composer',
|
||||
parentRequestId: parentRequestId?.trim() || null,
|
||||
promptContextRef: promptContextRef ?? null,
|
||||
status: 'queued',
|
||||
statusMessage: '대기열 등록',
|
||||
userMessageId: optimisticUserMessage.id,
|
||||
@@ -582,6 +585,7 @@ export function useConversationComposerController({
|
||||
chatTypeLabel: requestChatTypeLabel,
|
||||
requestOrigin: origin ?? 'composer',
|
||||
parentRequestId: parentRequestId?.trim() || null,
|
||||
promptContextRef: promptContextRef ?? null,
|
||||
status: 'accepted',
|
||||
statusMessage: '요청을 접수했습니다.',
|
||||
userMessageId: optimisticUserMessage.id,
|
||||
|
||||
@@ -36,6 +36,7 @@ function mergeConversationRequests(
|
||||
...item,
|
||||
requestOrigin: item.requestOrigin ?? previousItem.requestOrigin ?? null,
|
||||
parentRequestId: item.parentRequestId?.trim() || previousItem.parentRequestId?.trim() || null,
|
||||
promptContextRef: item.promptContextRef ?? previousItem.promptContextRef ?? null,
|
||||
statusMessage: nextStatusMessage,
|
||||
userMessageId: item.userMessageId ?? previousItem.userMessageId,
|
||||
userText: nextUserText,
|
||||
|
||||
@@ -14,7 +14,6 @@ type UseConversationViewControllerOptions = {
|
||||
activeView: 'chat' | 'runtime' | 'errors';
|
||||
isMobileViewport: boolean;
|
||||
previewItems: PreviewItem[];
|
||||
selectedChatTypeId: string | null;
|
||||
composerRef: { current: { focus: (options?: { cursor?: 'start' | 'end' | 'all' }) => void } | null };
|
||||
setActiveSystemStatus: (value: string | null) => void;
|
||||
setComposerAttachments: React.Dispatch<React.SetStateAction<ChatComposerAttachment[]>>;
|
||||
@@ -30,7 +29,6 @@ export function useConversationViewController({
|
||||
composerRef,
|
||||
isMobileViewport,
|
||||
previewItems,
|
||||
selectedChatTypeId,
|
||||
setActiveSystemStatus,
|
||||
setComposerAttachments,
|
||||
setCopiedMessageId,
|
||||
@@ -39,6 +37,8 @@ export function useConversationViewController({
|
||||
setIsSystemStatusPending,
|
||||
}: UseConversationViewControllerOptions) {
|
||||
const previousSessionIdRef = useRef(activeSessionId);
|
||||
const previousActiveViewRef = useRef(activeView);
|
||||
const hasInitializedComposerFocusRef = useRef(false);
|
||||
const [activePreviewId, setActivePreviewId] = useState<string | null>(null);
|
||||
const [activePreviewOverride, setActivePreviewOverride] = useState<PreviewItem | null>(null);
|
||||
const [isPreviewModalOpen, setIsPreviewModalOpen] = useState(false);
|
||||
@@ -158,12 +158,22 @@ export function useConversationViewController({
|
||||
}, [activePreview, isPreviewModalOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
const previousActiveView = previousActiveViewRef.current;
|
||||
previousActiveViewRef.current = activeView;
|
||||
|
||||
if (activeView !== 'chat' || isMobileViewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shouldFocusComposer = !hasInitializedComposerFocusRef.current || previousActiveView !== 'chat';
|
||||
hasInitializedComposerFocusRef.current = true;
|
||||
|
||||
if (!shouldFocusComposer) {
|
||||
return;
|
||||
}
|
||||
|
||||
composerRef.current?.focus({ cursor: 'end' });
|
||||
}, [activeView, composerRef, isMobileViewport, selectedChatTypeId]);
|
||||
}, [activeView, composerRef, isMobileViewport]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeView !== 'chat') {
|
||||
|
||||
@@ -7,9 +7,6 @@ import type {
|
||||
|
||||
const SCROLL_JUMP_HIDE_THRESHOLD = 24;
|
||||
const SCROLL_JUMP_MIN_OVERFLOW = 48;
|
||||
const SCROLL_JUMP_DIRECTION_THRESHOLD = 6;
|
||||
const SCROLL_JUMP_IDLE_HIDE_DELAY_MS = 900;
|
||||
|
||||
type UseConversationViewportControllerOptions = {
|
||||
activeConversation: ChatConversationSummary | null;
|
||||
activeQueuedComposerRequestsCount: number;
|
||||
@@ -55,7 +52,6 @@ export function useConversationViewportController({
|
||||
const systemStatusTimerRef = useRef<number | null>(null);
|
||||
const restoreAutoScrollFrameRef = useRef<number | null>(null);
|
||||
const showScrollToBottomRef = useRef(false);
|
||||
const scrollJumpIdleTimerRef = useRef<number | null>(null);
|
||||
const shouldStickToBottomRef = useRef(true);
|
||||
const lastViewportScrollTopRef = useRef(0);
|
||||
const autoScrollSuspendedUntilRef = useRef(0);
|
||||
@@ -80,13 +76,6 @@ export function useConversationViewportController({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const clearScrollJumpIdleTimer = useCallback(() => {
|
||||
if (scrollJumpIdleTimerRef.current !== null) {
|
||||
window.clearTimeout(scrollJumpIdleTimerRef.current);
|
||||
scrollJumpIdleTimerRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const syncShowScrollToBottom = useCallback((nextValue: boolean) => {
|
||||
if (showScrollToBottomRef.current === nextValue) {
|
||||
return;
|
||||
@@ -174,22 +163,12 @@ export function useConversationViewportController({
|
||||
lastViewportScrollTopRef.current = currentScrollTop;
|
||||
|
||||
if (maxScrollDistance < SCROLL_JUMP_MIN_OVERFLOW || shouldStickToBottom) {
|
||||
clearScrollJumpIdleTimer();
|
||||
syncShowScrollToBottom(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(scrollDelta) >= SCROLL_JUMP_DIRECTION_THRESHOLD) {
|
||||
clearScrollJumpIdleTimer();
|
||||
scrollJumpIdleTimerRef.current = window.setTimeout(() => {
|
||||
scrollJumpIdleTimerRef.current = null;
|
||||
syncShowScrollToBottom(false);
|
||||
}, SCROLL_JUMP_IDLE_HIDE_DELAY_MS);
|
||||
}
|
||||
|
||||
syncShowScrollToBottom(true);
|
||||
}, [
|
||||
clearScrollJumpIdleTimer,
|
||||
isAutoScrollSuspended,
|
||||
releaseAutoScrollSuspension,
|
||||
syncShowScrollToBottom,
|
||||
@@ -528,13 +507,12 @@ export function useConversationViewportController({
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearSystemStatusTimer();
|
||||
clearScrollJumpIdleTimer();
|
||||
|
||||
if (restoreAutoScrollFrameRef.current !== null) {
|
||||
window.cancelAnimationFrame(restoreAutoScrollFrameRef.current);
|
||||
}
|
||||
};
|
||||
}, [clearScrollJumpIdleTimer, clearSystemStatusTimer]);
|
||||
}, [clearSystemStatusTimer]);
|
||||
|
||||
return {
|
||||
activeSystemStatus,
|
||||
|
||||
Reference in New Issue
Block a user