feat(ui): enable drag-and-drop attachments and image previews in chat (#390)
* feat(BottomTerminalDock): add close button next to the fullscreen toggle in the dock * style: replace hardcoded gradient with theme value in shine text variant * fix(header): adapt instance button for desktop only * refactor(chat): polish sticky turn UX and message action rows for better readability Switch to stable sticky-only turn behavior and redesign user/assistant action controls (placement, hover rules, ordering, spacing, selection-safe clamp) to reduce visual noise and improve interaction flow. * feat(chat/message): refactor buttons in messages footer * feat: enhance image preview functionality in chat messages - Added a new ImagePreviewDialog component to handle image previews with navigation support. - Updated ToolOutputDialog to utilize the new ImagePreviewDialog for displaying images. - Modified the ToolPopupContent type to include a gallery of images and an index for the current image. - Removed the old inline image display logic from ToolOutputDialog. - Improved file handling in the file store, including better MIME type guessing and handling of server paths. - Introduced a new API endpoint for handling large session message payloads, allowing for better management of multi-file attachments. - Updated the VSCode bridge to support session message requests with appropriate headers and body handling. * feat(proxy): implement SSE forwarding and enhance generic API request handling * feat(chat): support submitting only queued messages * feat: add image preview transition state * fix: default VSCode view to draft and fixed sessions list regression
This commit is contained in:
committed by
GitHub
parent
39e625d8ec
commit
844562749d
@@ -25,7 +25,6 @@ interface SessionMemoryState {
|
||||
isZombie?: boolean;
|
||||
}
|
||||
|
||||
|
||||
interface UseChatScrollManagerOptions {
|
||||
currentSessionId: string | null;
|
||||
sessionMessages: ChatMessageRecord[];
|
||||
@@ -87,17 +86,11 @@ export const useChatScrollManager = ({
|
||||
const [isPinned, setIsPinned] = React.useState(true);
|
||||
|
||||
const lastSessionIdRef = React.useRef<string | null>(null);
|
||||
const currentSessionIdRef = React.useRef<string | null>(currentSessionId ?? null);
|
||||
const suppressUserScrollUntilRef = React.useRef<number>(0);
|
||||
const lastDirectScrollIntentAtRef = React.useRef<number>(0);
|
||||
const isPinnedRef = React.useRef(true);
|
||||
const lastScrollTopRef = React.useRef<number>(0);
|
||||
|
||||
|
||||
React.useEffect(() => {
|
||||
currentSessionIdRef.current = currentSessionId ?? null;
|
||||
}, [currentSessionId]);
|
||||
|
||||
const markProgrammaticScroll = React.useCallback(() => {
|
||||
suppressUserScrollUntilRef.current = Date.now() + PROGRAMMATIC_SCROLL_SUPPRESS_MS;
|
||||
}, []);
|
||||
@@ -330,8 +323,8 @@ export const useChatScrollManager = ({
|
||||
}
|
||||
}
|
||||
}, [getDistanceFromBottom, getPinThreshold, scrollToBottomInternal, updateScrollButtonVisibility]);
|
||||
|
||||
const getAnimationHandlers = React.useCallback((messageId: string): AnimationHandlers => {
|
||||
|
||||
const getAnimationHandlers = React.useCallback((messageId: string): AnimationHandlers => {
|
||||
const existing = animationHandlersRef.current.get(messageId);
|
||||
if (existing) {
|
||||
return existing;
|
||||
|
||||
Reference in New Issue
Block a user