Skip to content

Commit

Permalink
Reimplementing original imagebox
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksander Theo Strand/Users/aleksandertheostrand/repos/tetgpt-chat/venv/bin/python committed Nov 6, 2024
1 parent ec3085e commit cb86d5a
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 39 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,4 @@ dist-ssr
.aider*
.coverage

backend/README.md

myenv
backend/README.md
106 changes: 70 additions & 36 deletions frontend/src/components/atoms/elements/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useState } from 'react';
import { Suspense, lazy, useState } from 'react';

import Skeleton from '@mui/material/Skeleton';
import Lightbox from 'yet-another-react-lightbox';
import 'yet-another-react-lightbox/styles.css';
import Zoom from 'yet-another-react-lightbox/plugins/zoom';
import Download from 'yet-another-react-lightbox/plugins/download';

import { type IImageElement, useConfig } from '@chainlit/react-client';

import { FrameElement } from './Frame';

// Lazy load the Lightbox component and its dependencies
const LightboxWrapper = lazy(() => import('./LightboxWrapper'));

interface Props {
element: IImageElement;
}
Expand All @@ -22,15 +22,69 @@ const ImageElement = ({ element }: Props) => {
return null;
}

const enableLightbox = config.config?.features.image_lightbox && element.display === 'inline';
const enableLightbox =
config.config?.features.image_lightbox && element.display === 'inline';

const handleImageClick = () => {
if (enableLightbox) {
setLightboxOpen(true);
} else {
// Fall back to popup window behavior
const width = window.innerWidth / 2;
const height = window.innerHeight / 2;
const left = window.innerWidth / 4;
const top = window.innerHeight / 4;

const newWindow = window.open(
'',
'_blank',
`width=${width},height=${height},left=${left},top=${top}`
);
if (newWindow) {
newWindow.document.write(`
<html>
<head>
<title>${element.name}</title>
<link rel="icon" href="/favicon">
<style>
body {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
}
img {
max-width: 100%;
max-height: calc(100% - 50px);
}
a {
margin: 10px 0;
color: white;
text-decoration: none;
font-size: 15px;
background-color: rgba(255, 255, 255, 0.2);
padding: 8px 12px;
border-radius: 5px;
}
a:hover {
background-color: rgba(255, 255, 255, 0.4);
}
</style>
</head>
<body>
<img src="${element.url}" alt="${element.name}" />
<a href="${element.url}" download="${element.name}">Download</a>
</body>
</html>
`);
newWindow.document.close();
}
}
};


return (
<FrameElement>
{loading && <Skeleton variant="rectangular" width="100%" height={200} />}
Expand All @@ -50,35 +104,15 @@ const ImageElement = ({ element }: Props) => {
alt={element.name}
loading="lazy"
/>
{enableLightbox && (
<Lightbox
open={lightboxOpen}
close={() => setLightboxOpen(false)}
slides={[{ src: element.url }]}
carousel={{ finite: true }}
render={{ buttonPrev: () => null, buttonNext: () => null }}
plugins={[Zoom, Download]}
zoom={{
maxZoomPixelRatio: 5,
zoomInMultiplier: 2,
}}
download={{
download: async ({ slide }) => {
try {
const response = await fetch(slide.src, { mode: 'cors' });
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = element.name || 'image';
link.click();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Failed to download image:', error);
}
},
}}
/>
{enableLightbox && lightboxOpen && (
<Suspense fallback={<div>Loading...</div>}>
<LightboxWrapper
isOpen={lightboxOpen}
onClose={() => setLightboxOpen(false)}
imageUrl={element.url}
imageName={element.name}
/>
</Suspense>
)}
</FrameElement>
);
Expand Down
52 changes: 52 additions & 0 deletions frontend/src/components/atoms/elements/LightboxWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Lightbox from 'yet-another-react-lightbox';
import Download from 'yet-another-react-lightbox/plugins/download';
import Zoom from 'yet-another-react-lightbox/plugins/zoom';

import 'yet-another-react-lightbox/styles.css';

interface LightboxWrapperProps {
isOpen: boolean;
onClose: () => void;
imageUrl: string;
imageName: string;
}

const LightboxWrapper = ({
isOpen,
onClose,
imageUrl,
imageName
}: LightboxWrapperProps) => {
return (
<Lightbox
open={isOpen}
close={onClose}
slides={[{ src: imageUrl }]}
carousel={{ finite: true }}
render={{ buttonPrev: () => null, buttonNext: () => null }}
plugins={[Zoom, Download]}
zoom={{
maxZoomPixelRatio: 5,
zoomInMultiplier: 2
}}
download={{
download: async ({ slide }) => {
try {
const response = await fetch(slide.src, { mode: 'cors' });
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = imageName || 'image';
link.click();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error('Failed to download image:', error);
}
}
}}
/>
);
};

export default LightboxWrapper;

0 comments on commit cb86d5a

Please sign in to comment.