improving bg colors and adding borders

This commit is contained in:
PhilReact 2025-04-26 18:03:27 +03:00
parent 4fa9aa3c91
commit c4520b960d
14 changed files with 527 additions and 483 deletions

View File

@ -1471,6 +1471,7 @@ function App() {
sx={{ sx={{
height: '100%', height: '100%',
justifyContent: 'space-between', justifyContent: 'space-between',
borderLeft: `1px solid ${theme.palette.border.subtle}`,
}} }}
> >
<Box <Box

View File

@ -101,7 +101,6 @@ export const AnnouncementItem = ({
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{message?.name} {message?.name}

View File

@ -997,6 +997,7 @@ export const ChatGroup = ({
opacity: hide ? 0 : 1, opacity: hide ? 0 : 1,
position: hide ? 'absolute' : 'relative', position: hide ? 'absolute' : 'relative',
width: '100%', width: '100%',
padding: '10px',
}} }}
> >
<ChatList <ChatList
@ -1021,7 +1022,7 @@ export const ChatGroup = ({
{(!!secretKey || isPrivate === false) && ( {(!!secretKey || isPrivate === false) && (
<div <div
style={{ style={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.surface,
bottom: isFocusedParent ? '0px' : 'unset', bottom: isFocusedParent ? '0px' : 'unset',
boxSizing: 'border-box', boxSizing: 'border-box',
display: 'flex', display: 'flex',
@ -1034,6 +1035,8 @@ export const ChatGroup = ({
top: isFocusedParent ? '0px' : 'unset', top: isFocusedParent ? '0px' : 'unset',
width: '100%', width: '100%',
zIndex: isFocusedParent ? 5 : 'unset', zIndex: isFocusedParent ? 5 : 'unset',
border: `1px solid ${theme.palette.border.subtle}`,
borderRadius: '10px',
}} }}
> >
<div <div

View File

@ -2,7 +2,7 @@ import { useCallback, useState, useEffect, useRef, useMemo } from 'react';
import { useVirtualizer } from '@tanstack/react-virtual'; import { useVirtualizer } from '@tanstack/react-virtual';
import { MessageItem } from './MessageItem'; import { MessageItem } from './MessageItem';
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'; import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
import { Box, Typography, useTheme } from '@mui/material'; import { Box, Button, Typography, useTheme } from '@mui/material';
import { ChatOptions } from './ChatOptions'; import { ChatOptions } from './ChatOptions';
import ErrorBoundary from '../../common/ErrorBoundary'; import ErrorBoundary from '../../common/ErrorBoundary';
@ -407,10 +407,11 @@ export const ChatList = ({
</button> </button>
)} )}
{showScrollDownButton && !showScrollButton && ( {showScrollDownButton && !showScrollButton && (
<button <Button
onClick={() => scrollToBottom()} onClick={() => scrollToBottom()}
variant="contained"
style={{ style={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.surface,
border: 'none', border: 'none',
borderRadius: '20px', borderRadius: '20px',
bottom: 20, bottom: 20,
@ -422,10 +423,11 @@ export const ChatList = ({
position: 'absolute', position: 'absolute',
right: 20, right: 20,
zIndex: 10, zIndex: 10,
textTransform: 'none',
}} }}
> >
Scroll to bottom Scroll to bottom
</button> </Button>
)} )}
</div> </div>
{enableMentions && (hasSecretKey || isPrivate === false) && ( {enableMentions && (hasSecretKey || isPrivate === false) && (

View File

@ -767,7 +767,6 @@ const ShowMessage = ({ message, goToMessage, messages }) => {
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{message?.senderName} {message?.senderName}

View File

@ -248,7 +248,6 @@ export const MessageItem = React.memo(
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{message?.senderName || message?.sender} {message?.senderName || message?.sender}
@ -304,7 +303,7 @@ export const MessageItem = React.memo(
<Spacer height="20px" /> <Spacer height="20px" />
<Box <Box
sx={{ sx={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.surface,
borderRadius: '5px', borderRadius: '5px',
cursor: 'pointer', cursor: 'pointer',
display: 'flex', display: 'flex',
@ -319,9 +318,10 @@ export const MessageItem = React.memo(
> >
<Box <Box
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.text.primary,
height: '100%', height: '100%',
width: '5px', width: '5px',
flexShrink: 0,
}} }}
/> />
<Box <Box
@ -571,7 +571,7 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
return ( return (
<Box <Box
sx={{ sx={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.surface,
borderRadius: '5px', borderRadius: '5px',
cursor: 'pointer', cursor: 'pointer',
display: 'flex', display: 'flex',
@ -584,9 +584,10 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
> >
<Box <Box
sx={{ sx={{
background: theme.palette.background.default, background: theme.palette.text.primary,
height: '100%', height: '100%',
width: '5px', width: '5px',
flexShrink: 0,
}} }}
/> />
<Box <Box

View File

@ -40,6 +40,8 @@ export const DesktopSideBar = ({
gap: '25px', gap: '25px',
height: '100vh', height: '100vh',
width: '60px', width: '60px',
backgroundColor: theme.palette.background.surface,
borderRight: `1px solid ${theme.palette.border.subtle}`,
}} }}
> >
<ButtonBase <ButtonBase

View File

@ -1,5 +1,5 @@
import React, { useContext, useEffect, useMemo, useRef, useState } from "react"; import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import { MyContext, getBaseApiReact } from "../../App"; import { MyContext, getBaseApiReact } from '../../App';
import { import {
Card, Card,
CardContent, CardContent,
@ -15,285 +15,294 @@ import {
Dialog, Dialog,
IconButton, IconButton,
CircularProgress, CircularProgress,
} from "@mui/material"; } from '@mui/material';
import { base64ToBlobUrl } from "../../utils/fileReading"; import { base64ToBlobUrl } from '../../utils/fileReading';
import { saveFileToDiskGeneric } from "../../utils/generateWallet/generateWallet"; import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet';
import AttachmentIcon from '@mui/icons-material/Attachment'; import AttachmentIcon from '@mui/icons-material/Attachment';
import RefreshIcon from "@mui/icons-material/Refresh"; import RefreshIcon from '@mui/icons-material/Refresh';
import OpenInNewIcon from "@mui/icons-material/OpenInNew"; import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import { CustomLoader } from "../../common/CustomLoader"; import { CustomLoader } from '../../common/CustomLoader';
import { Spacer } from "../../common/Spacer"; import { Spacer } from '../../common/Spacer';
import { FileAttachmentContainer, FileAttachmentFont } from "./Embed-styles"; import { FileAttachmentContainer, FileAttachmentFont } from './Embed-styles';
import DownloadIcon from "@mui/icons-material/Download"; import DownloadIcon from '@mui/icons-material/Download';
import SaveIcon from '@mui/icons-material/Save'; import SaveIcon from '@mui/icons-material/Save';
import { useSetRecoilState } from "recoil"; import { useSetRecoilState } from 'recoil';
import { blobControllerAtom } from "../../atoms/global"; import { blobControllerAtom } from '../../atoms/global';
import { decodeIfEncoded } from "../../utils/decode"; import { decodeIfEncoded } from '../../utils/decode';
export const AttachmentCard = ({ export const AttachmentCard = ({
resourceData, resourceData,
resourceDetails, resourceDetails,
owner, owner,
refresh, refresh,
openExternal, openExternal,
external, external,
isLoadingParent, isLoadingParent,
errorMsg, errorMsg,
encryptionType, encryptionType,
selectedGroupId selectedGroupId,
}) => { }) => {
const [isOpen, setIsOpen] = useState(true);
const { downloadResource } = useContext(MyContext);
const [isOpen, setIsOpen] = useState(true); const saveToDisk = async () => {
const { downloadResource } = useContext(MyContext); const { name, service, identifier } = resourceData;
const saveToDisk = async ()=> { const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}`;
const { name, service, identifier } = resourceData; fetch(url)
.then((response) => response.blob())
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}`; .then(async (blob) => {
fetch(url) await saveFileToDiskGeneric(blob, resourceData?.fileName);
.then(response => response.blob()) })
.then(async blob => { .catch((error) => {
await saveFileToDiskGeneric(blob, resourceData?.fileName) console.error('Error fetching the video:', error);
}) });
.catch(error => { };
console.error("Error fetching the video:", error);
}); const saveToDiskEncrypted = async () => {
} let blobUrl;
try {
const saveToDiskEncrypted = async ()=> { const { name, service, identifier, key } = resourceData;
let blobUrl
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`;
const res = await fetch(url);
const data = await res.text();
let decryptedData;
try { try {
const { name, service, identifier,key } = resourceData; if (key && encryptionType === 'private') {
decryptedData = await window.sendMessage(
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`; 'DECRYPT_DATA_WITH_SHARING_KEY',
const res = await fetch(url)
const data = await res.text(); {
let decryptedData encryptedData: data,
try { key: decodeURIComponent(key),
if(key && encryptionType === 'private'){ }
decryptedData = await window.sendMessage( );
"DECRYPT_DATA_WITH_SHARING_KEY", }
if (encryptionType === 'group') {
{ decryptedData = await window.sendMessage(
encryptedData: data, 'DECRYPT_QORTAL_GROUP_DATA',
key: decodeURIComponent(key),
} {
data64: data,
); groupId: selectedGroupId,
} }
if(encryptionType === 'group'){ );
decryptedData = await window.sendMessage(
"DECRYPT_QORTAL_GROUP_DATA",
{
data64: data,
groupId: selectedGroupId,
}
);
}
} catch (error) {
throw new Error('Unable to decrypt')
} }
if (!decryptedData || decryptedData?.error) throw new Error("Could not decrypt data");
blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType)
const response = await fetch(blobUrl);
const blob = await response.blob();
await saveFileToDiskGeneric(blob, resourceData?.fileName)
} catch (error) { } catch (error) {
console.error(error) throw new Error('Unable to decrypt');
} finally { }
if(blobUrl){
URL.revokeObjectURL(blobUrl); if (!decryptedData || decryptedData?.error)
} throw new Error('Could not decrypt data');
blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType);
const response = await fetch(blobUrl);
const blob = await response.blob();
await saveFileToDiskGeneric(blob, resourceData?.fileName);
} catch (error) {
console.error(error);
} finally {
if (blobUrl) {
URL.revokeObjectURL(blobUrl);
} }
} }
return ( };
<Card return (
<Card
sx={{
backgroundColor: '#1F2023',
height: '250px',
// height: isOpen ? "auto" : "150px",
}}
>
<Box
sx={{ sx={{
backgroundColor: "#1F2023", display: 'flex',
height: "250px", alignItems: 'center',
// height: isOpen ? "auto" : "150px", justifyContent: 'space-between',
padding: '16px 16px 0px 16px',
}} }}
> >
<Box <Box
sx={{ sx={{
display: "flex", display: 'flex',
alignItems: "center", alignItems: 'center',
justifyContent: "space-between", gap: '10px',
padding: "16px 16px 0px 16px",
}} }}
> >
<Box <AttachmentIcon
sx={{ sx={{
display: "flex", color: 'white',
alignItems: "center",
gap: "10px",
}} }}
> />
<AttachmentIcon <Typography>ATTACHMENT embed</Typography>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: '10px',
}}
>
<ButtonBase>
<RefreshIcon
onClick={refresh}
sx={{ sx={{
color: "white", fontSize: '24px',
color: 'white',
}} }}
/> />
<Typography>ATTACHMENT embed</Typography> </ButtonBase>
</Box> {external && (
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "10px",
}}
>
<ButtonBase> <ButtonBase>
<RefreshIcon <OpenInNewIcon
onClick={refresh} onClick={openExternal}
sx={{ sx={{
fontSize: "24px", fontSize: '24px',
color: "white", color: 'white',
}} }}
/> />
</ButtonBase> </ButtonBase>
{external && (
<ButtonBase>
<OpenInNewIcon
onClick={openExternal}
sx={{
fontSize: "24px",
color: "white",
}}
/>
</ButtonBase>
)}
</Box>
</Box>
<Box
sx={{
padding: "8px 16px 8px 16px",
}}
>
<Typography
sx={{
fontSize: "12px",
color: "white",
}}
>
Created by {decodeIfEncoded(owner)}
</Typography>
<Typography
sx={{
fontSize: "12px",
color: "cadetblue",
}}
>
{encryptionType === 'private' ? "ENCRYPTED" : encryptionType === 'group' ? 'GROUP ENCRYPTED' : "Not encrypted"}
</Typography>
</Box>
<Divider sx={{ borderColor: "rgb(255 255 255 / 10%)" }} />
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
alignItems: "center",
}}
>
{isLoadingParent && isOpen && (
<Box
sx={{
width: "100%",
display: "flex",
justifyContent: "center",
}}
>
{" "}
<CustomLoader />{" "}
</Box>
)} )}
{errorMsg && ( </Box>
<Box </Box>
<Box
sx={{
padding: '8px 16px 8px 16px',
}}
>
<Typography
sx={{
fontSize: '12px',
color: 'white',
}}
>
Created by {decodeIfEncoded(owner)}
</Typography>
<Typography
sx={{
fontSize: '12px',
}}
>
{encryptionType === 'private'
? 'ENCRYPTED'
: encryptionType === 'group'
? 'GROUP ENCRYPTED'
: 'Not encrypted'}
</Typography>
</Box>
<Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} />
<Box
sx={{
display: 'flex',
flexDirection: 'column',
width: '100%',
alignItems: 'center',
}}
>
{isLoadingParent && isOpen && (
<Box
sx={{
width: '100%',
display: 'flex',
justifyContent: 'center',
}}
>
{' '}
<CustomLoader />{' '}
</Box>
)}
{errorMsg && (
<Box
sx={{
width: '100%',
display: 'flex',
justifyContent: 'center',
}}
>
{' '}
<Typography
sx={{ sx={{
width: "100%", fontSize: '14px',
display: "flex", color: 'var(--danger)',
justifyContent: "center",
}} }}
> >
{" "} {errorMsg}
</Typography>{' '}
</Box>
)}
</Box>
<Box>
<CardContent>
{resourceData?.fileName && (
<>
<Typography <Typography
sx={{ sx={{
fontSize: "14px", fontSize: '14px',
color: "var(--danger)",
}} }}
> >
{errorMsg} {resourceData?.fileName}
</Typography>{" "} </Typography>
</Box> <Spacer height="10px" />
</>
)} )}
</Box> <ButtonBase
sx={{
<Box> width: '90%',
<CardContent> maxWidth: '400px',
{resourceData?.fileName && ( }}
onClick={() => {
if (resourceDetails?.status?.status === 'READY') {
if (encryptionType) {
saveToDiskEncrypted();
return;
}
saveToDisk();
return;
}
downloadResource(resourceData);
}}
>
<FileAttachmentContainer>
<Typography>
{resourceDetails?.status?.status === 'DOWNLOADED'
? 'BUILDING'
: resourceDetails?.status?.status}
</Typography>
{!resourceDetails && (
<> <>
<Typography sx={{ <DownloadIcon />
fontSize: '14px' <FileAttachmentFont>Download File</FileAttachmentFont>
}}>{resourceData?.fileName}</Typography>
<Spacer height="10px" />
</> </>
)} )}
<ButtonBase sx={{ {resourceDetails &&
width: '90%', resourceDetails?.status?.status !== 'READY' &&
maxWidth: '400px' resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && (
}} onClick={()=> { <>
if(resourceDetails?.status?.status === 'READY'){ <CircularProgress
if(encryptionType){ sx={{
saveToDiskEncrypted() color: 'white',
return }}
} size={20}
saveToDisk() />
return <FileAttachmentFont>
} Downloading:{' '}
downloadResource(resourceData) {resourceDetails?.status?.percentLoaded || '0'}%
}}> </FileAttachmentFont>
</>
<FileAttachmentContainer > )}
<Typography>{resourceDetails?.status?.status === 'DOWNLOADED' ? 'BUILDING' : resourceDetails?.status?.status}</Typography> {resourceDetails &&
{!resourceDetails && ( resourceDetails?.status?.status === 'READY' && (
<> <>
<DownloadIcon /> <SaveIcon />
<FileAttachmentFont>Download File</FileAttachmentFont> <FileAttachmentFont>Save to Disk</FileAttachmentFont>
</>
</> )}
)} </FileAttachmentContainer>
{resourceDetails && resourceDetails?.status?.status !== 'READY' && resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && ( </ButtonBase>
<> </CardContent>
<CircularProgress sx={{ </Box>
color: 'white' </Card>
}} size={20} /> );
<FileAttachmentFont>Downloading: {resourceDetails?.status?.percentLoaded || '0'}%</FileAttachmentFont> };
</>
)}
{resourceDetails && resourceDetails?.status?.status === 'READY' && (
<>
<SaveIcon />
<FileAttachmentFont>Save to Disk</FileAttachmentFont>
</>
)}
</FileAttachmentContainer>
</ButtonBase>
</CardContent>
</Box>
</Card>
);
};

View File

@ -1,265 +1,265 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react';
import { import {
Card, Card,
CardContent, CardContent,
Typography, Typography,
Box, Box,
ButtonBase, ButtonBase,
Divider, Divider,
Dialog, Dialog,
IconButton, IconButton,
} from '@mui/material';
} from "@mui/material"; import RefreshIcon from '@mui/icons-material/Refresh';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import RefreshIcon from "@mui/icons-material/Refresh"; import { CustomLoader } from '../../common/CustomLoader';
import OpenInNewIcon from "@mui/icons-material/OpenInNew"; import ImageIcon from '@mui/icons-material/Image';
import { CustomLoader } from "../../common/CustomLoader"; import CloseIcon from '@mui/icons-material/Close';
import ImageIcon from "@mui/icons-material/Image"; import { decodeIfEncoded } from '../../utils/decode';
import CloseIcon from "@mui/icons-material/Close";
import { decodeIfEncoded } from "../../utils/decode";
export const ImageCard = ({ export const ImageCard = ({
image, image,
fetchImage, fetchImage,
owner, owner,
refresh, refresh,
openExternal, openExternal,
external, external,
isLoadingParent, isLoadingParent,
errorMsg, errorMsg,
encryptionType, encryptionType,
}) => { }) => {
const [isOpen, setIsOpen] = useState(true); const [isOpen, setIsOpen] = useState(true);
const [height, setHeight] = useState('400px') const [height, setHeight] = useState('400px');
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
fetchImage(); fetchImage();
} }
}, [isOpen]); }, [isOpen]);
// useEffect(()=> { // useEffect(()=> {
// if(errorMsg){ // if(errorMsg){
// setHeight('300px') // setHeight('300px')
// } // }
// }, [errorMsg]) // }, [errorMsg])
return ( return (
<Card <Card
sx={{
backgroundColor: '#1F2023',
height: height,
transition: 'height 0.6s ease-in-out',
}}
>
<Box
sx={{ sx={{
backgroundColor: "#1F2023", display: 'flex',
height: height, alignItems: 'center',
transition: "height 0.6s ease-in-out", justifyContent: 'space-between',
padding: '16px 16px 0px 16px',
}} }}
> >
<Box <Box
sx={{ sx={{
display: "flex", display: 'flex',
alignItems: "center", alignItems: 'center',
justifyContent: "space-between", gap: '10px',
padding: "16px 16px 0px 16px",
}} }}
> >
<Box <ImageIcon
sx={{ sx={{
display: "flex", color: 'white',
alignItems: "center",
gap: "10px",
}} }}
> />
<ImageIcon <Typography>IMAGE embed</Typography>
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: '10px',
}}
>
<ButtonBase>
<RefreshIcon
onClick={refresh}
sx={{ sx={{
color: "white", fontSize: '24px',
color: 'white',
}} }}
/> />
<Typography>IMAGE embed</Typography> </ButtonBase>
</Box> {external && (
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "10px",
}}
>
<ButtonBase> <ButtonBase>
<RefreshIcon <OpenInNewIcon
onClick={refresh} onClick={openExternal}
sx={{ sx={{
fontSize: "24px", fontSize: '24px',
color: "white", color: 'white',
}} }}
/> />
</ButtonBase> </ButtonBase>
{external && ( )}
<ButtonBase> </Box>
<OpenInNewIcon </Box>
onClick={openExternal} <Box
sx={{ sx={{
fontSize: "24px", padding: '8px 16px 8px 16px',
color: "white", }}
}} >
/> <Typography
</ButtonBase> sx={{
)} fontSize: '12px',
color: 'white',
}}
>
Created by {decodeIfEncoded(owner)}
</Typography>
<Typography
sx={{
fontSize: '12px',
}}
>
{encryptionType === 'private'
? 'ENCRYPTED'
: encryptionType === 'group'
? 'GROUP ENCRYPTED'
: 'Not encrypted'}
</Typography>
</Box>
<Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} />
<Box
sx={{
display: 'flex',
flexDirection: 'column',
width: '100%',
alignItems: 'center',
}}
>
{isLoadingParent && isOpen && (
<Box
sx={{
width: '100%',
display: 'flex',
justifyContent: 'center',
}}
>
{' '}
<CustomLoader />{' '}
</Box> </Box>
</Box> )}
<Box {errorMsg && (
sx={{ <Box
padding: "8px 16px 8px 16px",
}}
>
<Typography
sx={{ sx={{
fontSize: "12px", width: '100%',
color: "white", display: 'flex',
justifyContent: 'center',
}} }}
> >
Created by {decodeIfEncoded(owner)} {' '}
</Typography> <Typography
<Typography
sx={{
fontSize: "12px",
color: "cadetblue",
}}
>
{encryptionType === 'private' ? "ENCRYPTED" : encryptionType === 'group' ? 'GROUP ENCRYPTED' : "Not encrypted"}
</Typography>
</Box>
<Divider sx={{ borderColor: "rgb(255 255 255 / 10%)" }} />
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
alignItems: "center",
}}
>
{isLoadingParent && isOpen && (
<Box
sx={{ sx={{
width: "100%", fontSize: '14px',
display: "flex", color: 'var(--danger)',
justifyContent: "center",
}} }}
> >
{" "} {errorMsg}
<CustomLoader />{" "} </Typography>{' '}
</Box> </Box>
)} )}
{errorMsg && ( </Box>
<Box
sx={{
width: "100%",
display: "flex",
justifyContent: "center",
}}
>
{" "}
<Typography
sx={{
fontSize: "14px",
color: "var(--danger)",
}}
>
{errorMsg}
</Typography>{" "}
</Box>
)}
</Box>
<Box>
<CardContent>
<ImageViewer src={image} />
</CardContent>
</Box>
</Card>
);
};
export function ImageViewer({ src, alt = "" }) { <Box>
const [isFullscreen, setIsFullscreen] = useState(false); <CardContent>
<ImageViewer src={image} />
const handleOpenFullscreen = () => setIsFullscreen(true); </CardContent>
const handleCloseFullscreen = () => setIsFullscreen(false); </Box>
</Card>
return ( );
<> };
{/* Image in container */}
export function ImageViewer({ src, alt = '' }) {
const [isFullscreen, setIsFullscreen] = useState(false);
const handleOpenFullscreen = () => setIsFullscreen(true);
const handleCloseFullscreen = () => setIsFullscreen(false);
return (
<>
{/* Image in container */}
<Box
sx={{
maxWidth: '100%', // Prevent horizontal overflow
display: 'flex',
justifyContent: 'center',
cursor: 'pointer',
}}
onClick={handleOpenFullscreen}
>
<img
src={src}
alt={alt}
style={{
maxWidth: '100%',
maxHeight: '450px', // Adjust max height for small containers
objectFit: 'contain', // Preserve aspect ratio
}}
/>
</Box>
{/* Fullscreen Viewer */}
<Dialog
open={isFullscreen}
onClose={handleCloseFullscreen}
maxWidth="lg"
fullWidth
fullScreen
sx={{
'& .MuiDialog-paper': {
margin: 0,
maxWidth: '100%',
width: '100%',
height: '100vh',
overflow: 'hidden', // Prevent scrollbars
},
}}
>
<Box <Box
sx={{ sx={{
maxWidth: "100%", // Prevent horizontal overflow position: 'relative',
display: "flex", width: '100%',
justifyContent: "center", height: '100%',
cursor: "pointer", display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000', // Optional: dark background for fullscreen mode
}} }}
onClick={handleOpenFullscreen}
> >
{/* Close Button */}
<IconButton
onClick={handleCloseFullscreen}
sx={{
position: 'absolute',
top: 8,
right: 8,
zIndex: 10,
color: 'white',
}}
>
<CloseIcon />
</IconButton>
{/* Fullscreen Image */}
<img <img
src={src} src={src}
alt={alt} alt={alt}
style={{ style={{
maxWidth: "100%", maxWidth: '100%',
maxHeight: "450px", // Adjust max height for small containers maxHeight: '100%',
objectFit: "contain", // Preserve aspect ratio objectFit: 'contain', // Preserve aspect ratio
}} }}
/> />
</Box> </Box>
</Dialog>
{/* Fullscreen Viewer */} </>
<Dialog );
open={isFullscreen} }
onClose={handleCloseFullscreen}
maxWidth="lg"
fullWidth
fullScreen
sx={{
"& .MuiDialog-paper": {
margin: 0,
maxWidth: "100%",
width: "100%",
height: "100vh",
overflow: "hidden", // Prevent scrollbars
},
}}
>
<Box
sx={{
position: "relative",
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#000", // Optional: dark background for fullscreen mode
}}
>
{/* Close Button */}
<IconButton
onClick={handleCloseFullscreen}
sx={{
position: "absolute",
top: 8,
right: 8,
zIndex: 10,
color: "white",
}}
>
<CloseIcon />
</IconButton>
{/* Fullscreen Image */}
<img
src={src}
alt={alt}
style={{
maxWidth: "100%",
maxHeight: "100%",
objectFit: "contain", // Preserve aspect ratio
}}
/>
</Box>
</Dialog>
</>
);
}

View File

@ -1556,12 +1556,13 @@ export const Group = ({
<div <div
style={{ style={{
alignItems: 'flex-start', alignItems: 'flex-start',
background: theme.palette.background.default, background: theme.palette.background.surface,
borderRadius: '0px 15px 15px 0px', borderRadius: '0px 15px 15px 0px',
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
height: '100%', height: '100%',
width: '380px', width: '380px',
padding: '0px 2px',
}} }}
> >
<Box <Box
@ -1789,8 +1790,9 @@ export const Group = ({
flexDirection: 'column', flexDirection: 'column',
alignItems: 'flex-start', alignItems: 'flex-start',
height: '100%', height: '100%',
background: theme.palette.background.default, background: theme.palette.background.surface,
borderRadius: '0px 15px 15px 0px', borderRadius: '0px 15px 15px 0px',
padding: '0px 2px',
}} }}
> >
<Box <Box

View File

@ -687,7 +687,6 @@ export const ListOfGroupPromotions = () => {
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{promotion?.name} {promotion?.name}
@ -698,7 +697,6 @@ export const ListOfGroupPromotions = () => {
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{promotion?.groupName} {promotion?.groupName}
@ -746,7 +744,6 @@ export const ListOfGroupPromotions = () => {
sx={{ sx={{
fontWight: 600, fontWight: 600,
fontFamily: 'Inter', fontFamily: 'Inter',
color: 'cadetBlue',
}} }}
> >
{promotion?.data} {promotion?.data}

View File

@ -15,12 +15,17 @@ const darkThemeOptions: ThemeOptions = {
}, },
background: { background: {
default: 'rgb(49, 51, 56)', default: 'rgb(49, 51, 56)',
paper: 'rgb(96, 96, 97)', paper: 'rgb(62, 64, 68)',
surface: 'rgb(58, 60, 65)',
}, },
text: { text: {
primary: 'rgb(255, 255, 255)', primary: 'rgb(255, 255, 255)',
secondary: 'rgb(179, 179, 179)', secondary: 'rgb(179, 179, 179)',
}, },
border: {
main: 'rgba(255, 255, 255, 0.12)',
subtle: 'rgba(255, 255, 255, 0.08)',
},
}, },
components: { components: {
MuiCard: { MuiCard: {

View File

@ -6,21 +6,26 @@ const lightThemeOptions: ThemeOptions = {
palette: { palette: {
mode: 'light', mode: 'light',
primary: { primary: {
main: 'rgba(244, 244, 251, 1)', main: 'rgb(162, 162, 221)', // old light becomes main
dark: 'rgb(113, 198, 212)', dark: 'rgb(113, 198, 212)',
light: 'rgb(162, 162, 221)', light: 'rgba(244, 244, 251, 1)', // former main becomes light
}, },
secondary: { secondary: {
main: 'rgba(194, 222, 236, 1)', main: 'rgba(194, 222, 236, 1)',
}, },
background: { background: {
default: 'rgba(250, 250, 250, 1)', default: 'rgba(250, 250, 250, 1)',
paper: 'rgb(228, 228, 228)', paper: 'rgb(220, 220, 220)', // darker card background
surface: 'rgb(240, 240, 240)', // optional middle gray for replies, side panels
}, },
text: { text: {
primary: 'rgba(0, 0, 0, 1)', primary: 'rgba(0, 0, 0, 1)',
secondary: 'rgba(82, 82, 82, 1)', secondary: 'rgba(82, 82, 82, 1)',
}, },
border: {
main: 'rgba(0, 0, 0, 0.12)',
subtle: 'rgba(0, 0, 0, 0.08)',
},
}, },
components: { components: {
MuiCard: { MuiCard: {

19
src/styles/theme.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
import '@mui/material/styles';
declare module '@mui/material/styles' {
interface TypeBackground {
surface: string;
}
interface Palette {
border: {
main: string;
subtle: string;
};
}
interface PaletteOptions {
border?: {
main?: string;
subtle?: string;
};
}
}