Travslate attachment

This commit is contained in:
Nicola Benaglia 2025-05-17 15:13:25 +02:00
parent 201f1cf66d
commit e4cb818932
4 changed files with 74 additions and 30 deletions

View File

@ -1,19 +1,12 @@
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { useContext, useState } from 'react';
import { MyContext, getBaseApiReact } from '../../App'; import { MyContext, getBaseApiReact } from '../../App';
import { import {
Card, Card,
CardContent, CardContent,
CardHeader,
Typography, Typography,
RadioGroup,
Radio,
FormControlLabel,
Button,
Box, Box,
ButtonBase, ButtonBase,
Divider, Divider,
Dialog,
IconButton,
CircularProgress, CircularProgress,
useTheme, useTheme,
} from '@mui/material'; } from '@mui/material';
@ -27,8 +20,8 @@ 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 { decodeIfEncoded } from '../../utils/decode'; import { decodeIfEncoded } from '../../utils/decode';
import { useTranslation } from 'react-i18next';
export const AttachmentCard = ({ export const AttachmentCard = ({
resourceData, resourceData,
@ -45,6 +38,7 @@ export const AttachmentCard = ({
const [isOpen, setIsOpen] = useState(true); const [isOpen, setIsOpen] = useState(true);
const { downloadResource } = useContext(MyContext); const { downloadResource } = useContext(MyContext);
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(['auth', 'core', 'group']);
const saveToDisk = async () => { const saveToDisk = async () => {
const { name, service, identifier } = resourceData; const { name, service, identifier } = resourceData;
@ -64,16 +58,15 @@ export const AttachmentCard = ({
let blobUrl; let blobUrl;
try { try {
const { name, service, identifier, key } = resourceData; const { name, service, identifier, key } = resourceData;
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`; const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`;
const res = await fetch(url); const res = await fetch(url);
const data = await res.text(); const data = await res.text();
let decryptedData; let decryptedData;
try { try {
if (key && encryptionType === 'private') { if (key && encryptionType === 'private') {
decryptedData = await window.sendMessage( decryptedData = await window.sendMessage(
'DECRYPT_DATA_WITH_SHARING_KEY', 'DECRYPT_DATA_WITH_SHARING_KEY',
{ {
encryptedData: data, encryptedData: data,
key: decodeURIComponent(key), key: decodeURIComponent(key),
@ -91,11 +84,19 @@ export const AttachmentCard = ({
); );
} }
} catch (error) { } catch (error) {
throw new Error('Unable to decrypt'); throw new Error(
t('auth:message.error.unable_decrypt', {
postProcess: 'capitalizeFirst',
})
);
} }
if (!decryptedData || decryptedData?.error) if (!decryptedData || decryptedData?.error)
throw new Error('Could not decrypt data'); throw new Error(
t('auth:message.error.decrypt_data', {
postProcess: 'capitalizeFirst',
})
);
blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType); blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType);
const response = await fetch(blobUrl); const response = await fetch(blobUrl);
const blob = await response.blob(); const blob = await response.blob();
@ -108,18 +109,18 @@ export const AttachmentCard = ({
} }
} }
}; };
return ( return (
<Card <Card
sx={{ sx={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
height: '250px', height: '250px',
// height: isOpen ? "auto" : "150px",
}} }}
> >
<Box <Box
sx={{ sx={{
display: 'flex',
alignItems: 'center', alignItems: 'center',
display: 'flex',
justifyContent: 'space-between', justifyContent: 'space-between',
padding: '16px 16px 0px 16px', padding: '16px 16px 0px 16px',
}} }}
@ -136,12 +137,15 @@ export const AttachmentCard = ({
color: theme.palette.text.primary, color: theme.palette.text.primary,
}} }}
/> />
<Typography>ATTACHMENT embed</Typography> <Typography>
{t('core:attachment', { postProcess: 'capitalizeAll' })}
</Typography>
</Box> </Box>
<Box <Box
sx={{ sx={{
display: 'flex',
alignItems: 'center', alignItems: 'center',
display: 'flex',
gap: '10px', gap: '10px',
}} }}
> >
@ -154,6 +158,7 @@ export const AttachmentCard = ({
}} }}
/> />
</ButtonBase> </ButtonBase>
{external && ( {external && (
<ButtonBase> <ButtonBase>
<OpenInNewIcon <OpenInNewIcon
@ -167,6 +172,7 @@ export const AttachmentCard = ({
)} )}
</Box> </Box>
</Box> </Box>
<Box <Box
sx={{ sx={{
padding: '8px 16px 8px 16px', padding: '8px 16px 8px 16px',
@ -177,35 +183,47 @@ export const AttachmentCard = ({
fontSize: '12px', fontSize: '12px',
}} }}
> >
Created by {decodeIfEncoded(owner)} {t('core:message.generic.created_by', {
owner: decodeIfEncoded(owner),
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
<Typography <Typography
sx={{ sx={{
fontSize: '12px', fontSize: '12px',
}} }}
> >
{encryptionType === 'private' {encryptionType === 'private'
? 'ENCRYPTED' ? t('core:message.generic.encrypted', {
postProcess: 'capitalizeAll',
})
: encryptionType === 'group' : encryptionType === 'group'
? 'GROUP ENCRYPTED' ? t('group:message.generic.group_encrypted', {
: 'Not encrypted'} postProcess: 'capitalizeAll',
})
: t('core:message.generic.encrypted_not', {
postProcess: 'capitalizeAll',
})}
</Typography> </Typography>
</Box> </Box>
<Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} /> <Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} />
<Box <Box
sx={{ sx={{
alignItems: 'center',
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
width: '100%', width: '100%',
alignItems: 'center',
}} }}
> >
{isLoadingParent && isOpen && ( {isLoadingParent && isOpen && (
<Box <Box
sx={{ sx={{
width: '100%',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
width: '100%',
}} }}
> >
{' '} {' '}
@ -215,9 +233,9 @@ export const AttachmentCard = ({
{errorMsg && ( {errorMsg && (
<Box <Box
sx={{ sx={{
width: '100%',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
width: '100%',
}} }}
> >
{' '} {' '}
@ -249,8 +267,8 @@ export const AttachmentCard = ({
)} )}
<ButtonBase <ButtonBase
sx={{ sx={{
width: '90%',
maxWidth: '400px', maxWidth: '400px',
width: '90%',
}} }}
onClick={() => { onClick={() => {
if (resourceDetails?.status?.status === 'READY') { if (resourceDetails?.status?.status === 'READY') {
@ -267,15 +285,23 @@ export const AttachmentCard = ({
<FileAttachmentContainer> <FileAttachmentContainer>
<Typography> <Typography>
{resourceDetails?.status?.status === 'DOWNLOADED' {resourceDetails?.status?.status === 'DOWNLOADED'
? 'BUILDING' ? t('core:message.error.generic.building', {
postProcess: 'capitalizeAll',
})
: resourceDetails?.status?.status} : resourceDetails?.status?.status}
</Typography> </Typography>
{!resourceDetails && ( {!resourceDetails && (
<> <>
<DownloadIcon /> <DownloadIcon />
<FileAttachmentFont>Download File</FileAttachmentFont> <FileAttachmentFont>
{t('core:action.download_file', {
postProcess: 'capitalizeFirst',
})}
</FileAttachmentFont>
</> </>
)} )}
{resourceDetails && {resourceDetails &&
resourceDetails?.status?.status !== 'READY' && resourceDetails?.status?.status !== 'READY' &&
resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && ( resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && (
@ -287,16 +313,23 @@ export const AttachmentCard = ({
}} }}
/> />
<FileAttachmentFont> <FileAttachmentFont>
Downloading:{' '} {t('core:message.generic.downloading', {
{resourceDetails?.status?.percentLoaded || '0'}% postProcess: 'capitalizeFirst',
})}
: {resourceDetails?.status?.percentLoaded || '0'}%
</FileAttachmentFont> </FileAttachmentFont>
</> </>
)} )}
{resourceDetails && {resourceDetails &&
resourceDetails?.status?.status === 'READY' && ( resourceDetails?.status?.status === 'READY' && (
<> <>
<SaveIcon /> <SaveIcon />
<FileAttachmentFont>Save to Disk</FileAttachmentFont> <FileAttachmentFont>
{t('core:action.save_disk', {
postProcess: 'capitalizeFirst',
})}
</FileAttachmentFont>
</> </>
)} )}
</FileAttachmentContainer> </FileAttachmentContainer>

View File

@ -35,9 +35,11 @@
"message": { "message": {
"error": { "error": {
"account_creation": "could not create account.", "account_creation": "could not create account.",
"decrypt_data": "could not decrypt data",
"field_not_found_json": "{{ field }} not found in JSON", "field_not_found_json": "{{ field }} not found in JSON",
"incorrect_password": "incorrect password", "incorrect_password": "incorrect password",
"invalid_secret_key": "secretKey is not valid", "invalid_secret_key": "secretKey is not valid",
"unable_decrypt": "unable to decrypt",
"unable_reencrypt_secret_key": "unable to re-encrypt secret key" "unable_reencrypt_secret_key": "unable to re-encrypt secret key"
}, },
"generic": { "generic": {

View File

@ -30,6 +30,7 @@
"decrypt": "decrypt", "decrypt": "decrypt",
"disable_enter": "disable enter", "disable_enter": "disable enter",
"download": "download", "download": "download",
"download_file": "download file",
"edit": "edit", "edit": "edit",
"enter_name": "enter a name", "enter_name": "enter a name",
"export": "export", "export": "export",
@ -61,6 +62,7 @@
"remove_reaction": "remove reaction", "remove_reaction": "remove reaction",
"return_apps_dashboard": "return to Apps Dashboard", "return_apps_dashboard": "return to Apps Dashboard",
"save": "save", "save": "save",
"save_disk": "save to disk",
"search": "search", "search": "search",
"search_apps": "search for apps", "search_apps": "search for apps",
"select_app_type": "select App Type", "select_app_type": "select App Type",
@ -84,6 +86,7 @@
"app_service_type": "app service type", "app_service_type": "app service type",
"apps_dashboard": "apps Dashboard", "apps_dashboard": "apps Dashboard",
"apps_official": "official Apps", "apps_official": "official Apps",
"attachment": "attachment",
"category": "category", "category": "category",
"category_other": "categories", "category_other": "categories",
"core": { "core": {
@ -156,11 +159,16 @@
}, },
"generic": { "generic": {
"avatar_size": "{{ size }} KB max. for GIFS", "avatar_size": "{{ size }} KB max. for GIFS",
"building": "building",
"created_by": "created by {{ owner }}",
"buy_order_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy order</span>", "buy_order_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy order</span>",
"buy_order_request_other": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy orders</span>", "buy_order_request_other": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy orders</span>",
"devmode_local_node": "please use your local node for dev mode! Logout and use Local node.", "devmode_local_node": "please use your local node for dev mode! Logout and use Local node.",
"downloading": "downloading",
"edited": "edited", "edited": "edited",
"editing_message": "editing message", "editing_message": "editing message",
"encrypted": "encrypted",
"encrypted_not": "not encrypted",
"fee_qort": "fee: {{ message }} QORT", "fee_qort": "fee: {{ message }} QORT",
"foreign_fee": "foreign fee: {{ message }}", "foreign_fee": "foreign fee: {{ message }}",
"mentioned": "mentioned", "mentioned": "mentioned",

View File

@ -70,6 +70,7 @@
"descrypt_wallet": "decrypting wallet...", "descrypt_wallet": "decrypting wallet...",
"encryption_key": "the group's first common encryption key is in the process of creation. Please wait a few minutes for it to be retrieved by the network. Checking every 2 minutes...", "encryption_key": "the group's first common encryption key is in the process of creation. Please wait a few minutes for it to be retrieved by the network. Checking every 2 minutes...",
"group_announcement": "group Announcements", "group_announcement": "group Announcements",
"group_encrypted": "group encrypted",
"group_invited_you": "{{group}} has invited you", "group_invited_you": "{{group}} has invited you",
"group_key_created": "first group key created.", "group_key_created": "first group key created.",
"group_member_list_changed": "the group member list has changed. Please re-encrypt the secret key.", "group_member_list_changed": "the group member list has changed. Please re-encrypt the secret key.",