LibreChat/client/src/components/Chat/Messages/Content/DialogImage.tsx

374 lines
12 KiB
TypeScript
Raw Normal View History

import { useState, useEffect, useCallback, useRef } from 'react';
📦 feat: Move Shared Components to `@librechat/client` (#8685) * feat: init @librechat/client * feat: Add common types and interfaces for accessibility, agents, artifacts, assistants, and tools * feat: Add jotai as a peer dependency * fix build client package * feat: cleanup unused types from common/index.ts - Remove 104 unused type exports from packages/client/src/common/index.ts - Keep only 7 actually used exports (93% reduction) - Add cleanup script with enhanced import pattern detection - Support both named imports and namespace imports (* as t) - Create automatic backups and comprehensive documentation - Maintain type safety with build verification - No breaking changes to existing code Kept exports: - TShowToast, Option, OptionWithIcon, DropdownValueSetter - MentionOption, NotificationSeverity, MenuItemProps Scripts: cleanup-common-types-safe.js, README-CLEANUP.md * fix: cleanup * fix: package; refactor: tsconfig * feat: add back `recoil` * fix: move dependencies to peerDependencies in client package * feat: add @librechat/client as a dependency in package.json and package-lock.json * feat: update client package configuration and dependencies - Added new dependencies for Rollup plugins and updated existing ones in package.json and package-lock.json. - Introduced a new Rollup configuration file for building the client package. - Refactored build scripts to include a dedicated build command for the client. - Updated TypeScript configuration for improved module resolution and type declaration output. - Integrated a Toast component from the client package into the main App component. * feat: enhance Rollup configuration for client package - Updated terser plugin settings to preserve directives like 'use client'. - Added custom warning handler to ignore "use client" directive warnings during the build process. * chore: rename package/client build script command * feat: update client package dependencies and Rollup configuration - Added rollup-plugin-postcss to package.json and updated package-lock.json. - Enhanced Rollup configuration to include postcss plugin for CSS handling. - Updated index.ts to export all components from the components directory for better modularity. * feat: add client package directory to update configuration - Included the 'client' package directory in the update.js configuration to ensure it is recognized during updates. * feat: export Toast component in client package - Added export for the Toast component in index.ts to enhance modularity and accessibility of components. * feat: /client transition to @librechat/client * chore: fixed formatting issues * fix: update peer dependencies in @librechat/client to prevent bundling them * fix: correct useSprings implementation in SplitText component * fix: circular dependencies in DataTable * fix: add remaining peer dependencies and match actual versions previously used in `client/package.json` * fix: correct frontend:ci script to include client package build * chore: enhance unused package detection for @librechat/client and improve dependency extraction * fix: add missing peer dependency for @radix-ui/react-collapsible * chore: include "packages/client" in unused i18next keys detection * test: update AgentFooter tests to use document.querySelector for spinner checks test: mock window.matchMedia in setupTests.js for consistent test environment * feat: add react-hook-form dependency and update FormInput component to use its types * chore: linting * refactor: remove unused defaultSelectedValues prop from MCPSelect and MultiSelect components * chore: linting * feat: update GitHub Actions workflow to publish @librechat/client * chore: update GitHub Actions workflow to install and build data-provider and client dependencies * chore: add missing @testing-library/react dependency to client package * chore: update tsconfig.json to exclude additional test files * chore: fix build issues, resolve latest LC changes * chore: move MCP components outside of `~/components/ui` * feat: implement dynamic theme system with environment variable support and Tailwind CSS integration * chore: remove unnecessary logging of sttExternal and ttsExternal in Speech component * chore: squashed cleanup commits chore: move @tanstack/react-virtual to dependencies and remove recoil from package.json chore: move dependencies to peerDependencies in package.json feat: update package.json and rollup.config.js to include jotai and enhance bundling configuration feat: update package.json and rollup.config.js to include jotai and enhance bundling configuration refactor: reorganize exports in index.ts for improved clarity refactor: remove unused types and interfaces from common files refactor: update peer dependencies and improve component typings - Removed duplicate peer dependencies from package.json and organized them. - Updated rollup.config.js to disable TypeScript checking during the build process. - Modified AnimatedTabs component to use React.ReactNode for label and content types, and added TypeScript workarounds for compatibility. - Enhanced Label and Separator components to accept an optional className prop and improved prop spreading. - Updated Slider component to include an optional className prop and refined prop handling for better type safety. refactor: clean up client workflow and update package dependencies refactor: update package dependencies and improve PostCSS and Rollup configurations chore: bump version to 0.1.2 in package.json chore: bump client version to 0.1.2 in package-lock.json chore: bump client version to 0.1.3 and update dependencies chore: bump client version to 0.1.4 and update @react-spring dependencies chore: update package version to 0.1.5 and adjust peer dependencies - Bump version in package.json from 0.1.4 to 0.1.5. - Update peer dependency for @tanstack/react-query to allow version 5.0.0. - Add @tanstack/react-table and @tanstack/react-virtual as dependencies. - Update various dependencies to their latest compatible versions. - Simplify postcss.config.js by removing unnecessary options. - Clean up rollup.config.js by removing ignored PostCSS warnings. - Update CheckboxButton component to cast icon as React JSX element. - Adjust Combobox component's class names for better styling. - Change DropdownPopup component to use React's namespace import. - Modify InputOTP component to use 'any' type for OTPInputContext. - Ensure displayLabel and value in ModelParameters are converted to strings. - Update MultiSearch component's placeholder to ensure it's a string. - Cast selectIcon in MultiSelect as React JSX element for consistency. - Update OGDialogTemplate to cast selectText as React JSX element. - Initialize animationRef in PixelCard with undefined for clarity. - Add TypeScript ignore comments in Select and SelectDropDown components for Radix UI type conflicts. - Ensure title in SelectDropDown is a string and adjust rendering of options. - Update useLocalize hook to cast options as any for compatibility. refactor: code structure; chore: translations cleanup chore: remove unused imports and clean up code in NewChat component refactor: enhance Menu component to support custom render functions for menu items style: update itemClassName in ToolsDropdown for improved UI consistency fix: merge conflicts chore: update @radix-ui/react-accordion to version 1.2.11 * refactor: remove unnecessary TypeScript type assertions in AnimatedTabs, Label, Separator, and Slider components * feat: enhance theme system with localStorage persistence and new theme atoms * chore: bump version of @librechat/client to 0.1.7 * chore: fix ci/cd warnings/errors related to linting and unused localization keys * chore: update dependencies for class-variance-authority, clsx, and match-sorter * chore: bump @librechat/client to v0.1.8 * feat: add utility colors for theme customization and remove unused tailwindConfig * v0.1.9 --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
2025-07-27 12:19:01 -04:00
import { Button, OGDialog, OGDialogContent, TooltipAnchor } from '@librechat/client';
import { X, ArrowDownToLine, PanelLeftOpen, PanelLeftClose, RotateCcw } from 'lucide-react';
import { useLocalize } from '~/hooks';
const getQualityStyles = (quality: string): string => {
if (quality === 'high') {
return 'bg-green-100 text-green-800';
}
if (quality === 'low') {
return 'bg-orange-100 text-orange-800';
}
return 'bg-gray-100 text-gray-800';
};
export default function DialogImage({ isOpen, onOpenChange, src = '', downloadImage, args }) {
const localize = useLocalize();
const [isPromptOpen, setIsPromptOpen] = useState(false);
const [imageSize, setImageSize] = useState<string | null>(null);
// Zoom and pan state
const [zoom, setZoom] = useState(1);
const [panX, setPanX] = useState(0);
const [panY, setPanY] = useState(0);
const [isDragging, setIsDragging] = useState(false);
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
const containerRef = useRef<HTMLDivElement>(null);
const getImageSize = useCallback(async (url: string) => {
try {
const response = await fetch(url, { method: 'HEAD' });
const contentLength = response.headers.get('Content-Length');
if (contentLength) {
const bytes = parseInt(contentLength, 10);
return formatFileSize(bytes);
}
const fullResponse = await fetch(url);
const blob = await fullResponse.blob();
return formatFileSize(blob.size);
} catch (error) {
console.error('Error getting image size:', error);
return null;
}
}, []);
const formatFileSize = (bytes: number): string => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
const getImageMaxWidth = () => {
// On mobile (when panel overlays), use full width minus padding
// On desktop, account for the side panel width
if (isPromptOpen) {
return window.innerWidth >= 640 ? 'calc(100vw - 22rem)' : 'calc(100vw - 2rem)';
}
return 'calc(100vw - 2rem)';
};
const resetZoom = useCallback(() => {
setZoom(1);
setPanX(0);
setPanY(0);
}, []);
const getCursor = () => {
if (zoom <= 1) return 'default';
return isDragging ? 'grabbing' : 'grab';
};
const handleDoubleClick = useCallback(() => {
if (zoom > 1) {
resetZoom();
} else {
// Zoom in to 2x on double click when at normal zoom
setZoom(2);
}
}, [zoom, resetZoom]);
const handleWheel = useCallback(
(e: React.WheelEvent<HTMLDivElement>) => {
e.preventDefault();
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
// Calculate zoom factor
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
const newZoom = Math.min(Math.max(zoom * zoomFactor, 1), 5);
if (newZoom === zoom) return;
// If zooming back to 1, reset pan to center the image
if (newZoom === 1) {
setZoom(1);
setPanX(0);
setPanY(0);
return;
}
// Calculate the zoom center relative to the current viewport
const containerCenterX = rect.width / 2;
const containerCenterY = rect.height / 2;
// Calculate new pan position to zoom towards mouse cursor
const zoomRatio = newZoom / zoom;
const deltaX = (mouseX - containerCenterX - panX) * (zoomRatio - 1);
const deltaY = (mouseY - containerCenterY - panY) * (zoomRatio - 1);
setZoom(newZoom);
setPanX(panX - deltaX);
setPanY(panY - deltaY);
},
[zoom, panX, panY],
);
const handleMouseDown = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
if (zoom <= 1) return;
setIsDragging(true);
setDragStart({
x: e.clientX - panX,
y: e.clientY - panY,
});
},
[zoom, panX, panY],
);
const handleMouseMove = useCallback(
(e: React.MouseEvent<HTMLDivElement>) => {
if (!isDragging || zoom <= 1) return;
const newPanX = e.clientX - dragStart.x;
const newPanY = e.clientY - dragStart.y;
setPanX(newPanX);
setPanY(newPanY);
},
[isDragging, dragStart, zoom],
);
const handleMouseUp = useCallback(() => {
setIsDragging(false);
}, []);
useEffect(() => {
const onKey = (e: KeyboardEvent) => e.key === 'Escape' && resetZoom();
document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
}, [resetZoom]);
useEffect(() => {
if (isOpen && src) {
getImageSize(src).then(setImageSize);
resetZoom();
}
}, [isOpen, src, getImageSize, resetZoom]);
// Ensure image is centered when zoom changes to 1
useEffect(() => {
if (zoom === 1) {
setPanX(0);
setPanY(0);
}
}, [zoom]);
// Reset pan when panel opens/closes to maintain centering
useEffect(() => {
if (zoom === 1) {
setPanX(0);
setPanY(0);
}
}, [isPromptOpen, zoom]);
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
return (
🖼️ feat: Tool Call and Loading UI Refresh, Image Resize Config (#7086) * ✨ feat: Enhance Spinner component with customizable properties and improved animation * 🔧 fix: Replace Loader with Spinner in RunCode component and update FilePreview to use Spinner for progress indication * ✨ feat: Refactor icons in CodeProgress and CancelledIcon components; enhance animation and styling in ExecuteCode and ProgressText components * ✨ feat: Refactor attachment handling in ExecuteCode component; replace individual attachment rendering with AttachmentGroup for improved structure * ✨ feat: Refactor dialog components for improved accessibility and styling; integrate Skeleton loading state in Image component * ✨ feat: Refactor ToolCall component to use ToolCallInfo for better structure; replace ToolPopover with AttachmentGroup; enhance ProgressText with error handling and improved UI elements * 🔧 fix: Remove unnecessary whitespace in ProgressText * 🔧 fix: Remove unnecessary margin from AgentFooter and AgentPanel components; clean up SidePanel imports * ✨ feat: Enhance ToolCall and ToolCallInfo components with improved styling; update translations and add warning text color to Tailwind config * 🔧 fix: Update import statement for useLocalize in ToolCallInfo component; fix: chatform transition * ✨ feat: Refactor ToolCall and ToolCallInfo components for improved structure and styling; add optimized code block for better output display * ✨ feat: Implement OpenAI image generation component; add progress tracking and localization for user feedback * 🔧 fix: Adjust base duration values for image generation; optimize timing for quality settings * chore: remove unnecessary space * ✨ feat: Enhance OpenAI image generation with editing capabilities; update localization for progress feedback * ✨ feat: Add download functionality to images; enhance DialogImage component with download button * ✨ feat: Enhance image resizing functionality; support custom percentage and pixel dimensions in resizeImageBuffer
2025-05-16 17:50:18 +02:00
<OGDialog open={isOpen} onOpenChange={onOpenChange}>
<OGDialogContent
showCloseButton={false}
className="h-full w-full rounded-none bg-transparent"
disableScroll={false}
overlayClassName="bg-surface-primary opacity-95 z-50"
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
>
<div
className={`ease-[cubic-bezier(0.175,0.885,0.32,1.275)] absolute left-0 top-0 z-10 flex items-center justify-between p-3 transition-all duration-500 sm:p-4 ${isPromptOpen ? 'right-0 sm:right-80' : 'right-0'}`}
>
<TooltipAnchor
description={localize('com_ui_close')}
render={
<Button
onClick={() => onOpenChange(false)}
variant="ghost"
className="h-10 w-10 p-0 hover:bg-surface-hover"
>
<X className="size-7 sm:size-6" />
</Button>
}
/>
<div className="flex items-center gap-1 sm:gap-2">
{zoom > 1 && (
<TooltipAnchor
description={localize('com_ui_reset_zoom')}
render={
<Button onClick={resetZoom} variant="ghost" className="h-10 w-10 p-0">
<RotateCcw className="size-6" />
</Button>
}
/>
)}
<TooltipAnchor
description={localize('com_ui_download')}
render={
<Button onClick={() => downloadImage()} variant="ghost" className="h-10 w-10 p-0">
<ArrowDownToLine className="size-6" />
</Button>
}
/>
<TooltipAnchor
description={
isPromptOpen
? localize('com_ui_hide_image_details')
: localize('com_ui_show_image_details')
}
render={
<Button
onClick={() => setIsPromptOpen(!isPromptOpen)}
variant="ghost"
className="h-10 w-10 p-0"
>
{isPromptOpen ? (
<PanelLeftOpen className="size-7 sm:size-6" />
) : (
<PanelLeftClose className="size-7 sm:size-6" />
)}
</Button>
}
/>
</div>
🖼️ feat: Tool Call and Loading UI Refresh, Image Resize Config (#7086) * ✨ feat: Enhance Spinner component with customizable properties and improved animation * 🔧 fix: Replace Loader with Spinner in RunCode component and update FilePreview to use Spinner for progress indication * ✨ feat: Refactor icons in CodeProgress and CancelledIcon components; enhance animation and styling in ExecuteCode and ProgressText components * ✨ feat: Refactor attachment handling in ExecuteCode component; replace individual attachment rendering with AttachmentGroup for improved structure * ✨ feat: Refactor dialog components for improved accessibility and styling; integrate Skeleton loading state in Image component * ✨ feat: Refactor ToolCall component to use ToolCallInfo for better structure; replace ToolPopover with AttachmentGroup; enhance ProgressText with error handling and improved UI elements * 🔧 fix: Remove unnecessary whitespace in ProgressText * 🔧 fix: Remove unnecessary margin from AgentFooter and AgentPanel components; clean up SidePanel imports * ✨ feat: Enhance ToolCall and ToolCallInfo components with improved styling; update translations and add warning text color to Tailwind config * 🔧 fix: Update import statement for useLocalize in ToolCallInfo component; fix: chatform transition * ✨ feat: Refactor ToolCall and ToolCallInfo components for improved structure and styling; add optimized code block for better output display * ✨ feat: Implement OpenAI image generation component; add progress tracking and localization for user feedback * 🔧 fix: Adjust base duration values for image generation; optimize timing for quality settings * chore: remove unnecessary space * ✨ feat: Enhance OpenAI image generation with editing capabilities; update localization for progress feedback * ✨ feat: Add download functionality to images; enhance DialogImage component with download button * ✨ feat: Enhance image resizing functionality; support custom percentage and pixel dimensions in resizeImageBuffer
2025-05-16 17:50:18 +02:00
</div>
{/* Main content area with image */}
<div
className={`ease-[cubic-bezier(0.175,0.885,0.32,1.275)] flex h-full transition-all duration-500 ${isPromptOpen ? 'mr-0 sm:mr-80' : 'mr-0'}`}
>
<div
ref={containerRef}
className="flex flex-1 items-center justify-center px-2 pb-4 pt-16 sm:px-4 sm:pt-20"
onWheel={handleWheel}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
onDoubleClick={handleDoubleClick}
style={{
cursor: getCursor(),
overflow: zoom > 1 ? 'hidden' : 'visible',
minHeight: 0, // Allow flexbox to shrink
}}
>
<div
className="flex items-center justify-center transition-transform duration-100 ease-out"
style={{
transform: `translate(${panX}px, ${panY}px) scale(${zoom})`,
transformOrigin: 'center center',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<img
src={src}
alt="Image"
className="block object-contain"
style={{
maxHeight: 'calc(100vh - 8rem)',
maxWidth: getImageMaxWidth(),
width: 'auto',
height: 'auto',
}}
/>
</div>
</div>
</div>
{/* Side Panel */}
<div
className={`sm:shadow-l-lg ease-[cubic-bezier(0.175,0.885,0.32,1.275)] fixed right-0 top-0 z-20 h-full w-full transform border-l border-border-light bg-surface-primary shadow-2xl backdrop-blur-sm transition-transform duration-500 sm:w-80 sm:rounded-l-2xl ${
isPromptOpen ? 'translate-x-0' : 'translate-x-full'
}`}
>
{/* Mobile pull handle - removed for cleaner look */}
<div className="h-full overflow-y-auto p-4 sm:p-6">
{/* Mobile close button */}
<div className="mb-4 flex items-center justify-between sm:hidden">
<h3 className="text-lg font-semibold text-text-primary">
{localize('com_ui_image_details')}
</h3>
<Button
onClick={() => setIsPromptOpen(false)}
variant="ghost"
className="h-12 w-12 p-0"
>
<X className="size-6" />
</Button>
</div>
<div className="mb-4 hidden sm:block">
<h3 className="mb-2 text-lg font-semibold text-text-primary">
{localize('com_ui_image_details')}
</h3>
<div className="mb-4 h-px bg-border-medium"></div>
</div>
<div className="space-y-4 sm:space-y-6">
{/* Prompt Section */}
<div>
<h4 className="mb-2 text-sm font-medium text-text-primary">
{localize('com_ui_prompt')}
</h4>
<div className="rounded-md bg-surface-tertiary p-3">
<p className="text-sm leading-relaxed text-text-primary">
{args?.prompt || 'No prompt available'}
</p>
</div>
</div>
{/* Generation Settings */}
<div>
<h4 className="mb-3 text-sm font-medium text-text-primary">
{localize('com_ui_generation_settings')}
</h4>
<div className="space-y-3">
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">{localize('com_ui_size')}:</span>
<span className="text-sm font-medium text-text-primary">
{args?.size || 'Unknown'}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">{localize('com_ui_quality')}:</span>
<span
className={`rounded px-2 py-1 text-xs font-medium capitalize ${getQualityStyles(args?.quality || '')}`}
>
{args?.quality || 'Standard'}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-text-primary">
{localize('com_ui_file_size')}:
</span>
<span className="text-sm font-medium text-text-primary">
{imageSize || 'Loading...'}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
🖼️ feat: Tool Call and Loading UI Refresh, Image Resize Config (#7086) * ✨ feat: Enhance Spinner component with customizable properties and improved animation * 🔧 fix: Replace Loader with Spinner in RunCode component and update FilePreview to use Spinner for progress indication * ✨ feat: Refactor icons in CodeProgress and CancelledIcon components; enhance animation and styling in ExecuteCode and ProgressText components * ✨ feat: Refactor attachment handling in ExecuteCode component; replace individual attachment rendering with AttachmentGroup for improved structure * ✨ feat: Refactor dialog components for improved accessibility and styling; integrate Skeleton loading state in Image component * ✨ feat: Refactor ToolCall component to use ToolCallInfo for better structure; replace ToolPopover with AttachmentGroup; enhance ProgressText with error handling and improved UI elements * 🔧 fix: Remove unnecessary whitespace in ProgressText * 🔧 fix: Remove unnecessary margin from AgentFooter and AgentPanel components; clean up SidePanel imports * ✨ feat: Enhance ToolCall and ToolCallInfo components with improved styling; update translations and add warning text color to Tailwind config * 🔧 fix: Update import statement for useLocalize in ToolCallInfo component; fix: chatform transition * ✨ feat: Refactor ToolCall and ToolCallInfo components for improved structure and styling; add optimized code block for better output display * ✨ feat: Implement OpenAI image generation component; add progress tracking and localization for user feedback * 🔧 fix: Adjust base duration values for image generation; optimize timing for quality settings * chore: remove unnecessary space * ✨ feat: Enhance OpenAI image generation with editing capabilities; update localization for progress feedback * ✨ feat: Add download functionality to images; enhance DialogImage component with download button * ✨ feat: Enhance image resizing functionality; support custom percentage and pixel dimensions in resizeImageBuffer
2025-05-16 17:50:18 +02:00
</OGDialogContent>
</OGDialog>
feat: Vision Support + New UI (#1203) * feat: add timer duration to showToast, show toast for preset selection * refactor: replace old /chat/ route with /c/. e2e tests will fail here * refactor: move typedefs to root of /api/ and add a few to assistant types in TS * refactor: reorganize data-provider imports, fix dependency cycle, strategize new plan to separate react dependent packages * feat: add dataService for uploading images * feat(data-provider): add mutation keys * feat: file resizing and upload * WIP: initial API image handling * fix: catch JSON.parse of localStorage tools * chore: experimental: use module-alias for absolute imports * refactor: change temp_file_id strategy * fix: updating files state by using Map and defining react query callbacks in a way that keeps them during component unmount, initial delete handling * feat: properly handle file deletion * refactor: unexpose complete filepath and resize from server for higher fidelity * fix: make sure resized height, width is saved, catch bad requests * refactor: use absolute imports * fix: prevent setOptions from being called more than once for OpenAIClient, made note to fix for PluginsClient * refactor: import supportsFiles and models vars from schemas * fix: correctly replace temp file id * refactor(BaseClient): use absolute imports, pass message 'opts' to buildMessages method, count tokens for nested objects/arrays * feat: add validateVisionModel to determine if model has vision capabilities * chore(checkBalance): update jsdoc * feat: formatVisionMessage: change message content format dependent on role and image_urls passed * refactor: add usage to File schema, make create and updateFile, correctly set and remove TTL * feat: working vision support TODO: file size, type, amount validations, making sure they are styled right, and making sure you can add images from the clipboard/dragging * feat: clipboard support for uploading images * feat: handle files on drop to screen, refactor top level view code to Presentation component so the useDragHelpers hook has ChatContext * fix(Images): replace uploaded images in place * feat: add filepath validation to protect sensitive files * fix: ensure correct file_ids are push and not the Map key values * fix(ToastContext): type issue * feat: add basic file validation * fix(useDragHelpers): correct context issue with `files` dependency * refactor: consolidate setErrors logic to setError * feat: add dialog Image overlay on image click * fix: close endpoints menu on click * chore: set detail to auto, make note for configuration * fix: react warning (button desc. of button) * refactor: optimize filepath handling, pass file_ids to images for easier re-use * refactor: optimize image file handling, allow re-using files in regen, pass more file metadata in messages * feat: lazy loading images including use of upload preview * fix: SetKeyDialog closing, stopPropagation on Dialog content click * style(EndpointMenuItem): tighten up the style, fix dark theme showing in lightmode, make menu more ux friendly * style: change maxheight of all settings textareas to 138px from 300px * style: better styling for textarea and enclosing buttons * refactor(PresetItems): swap back edit and delete icons * feat: make textarea placeholder dynamic to endpoint * style: show user hover buttons only on hover when message is streaming * fix: ordered list not going past 9, fix css * feat: add User/AI labels; style: hide loading spinner * feat: add back custom footer, change original footer text * feat: dynamic landing icons based on endpoint * chore: comment out assistants route * fix: autoScroll to newest on /c/ view * fix: Export Conversation on new UI * style: match message style of official more closely * ci: fix api jest unit tests, comment out e2e tests for now as they will fail until addressed * feat: more file validation and use blob in preview field, not filepath, to fix temp deletion * feat: filefilter for multer * feat: better AI labels based on custom name, model, and endpoint instead of `ChatGPT`
2023-11-21 20:12:48 -05:00
);
}