mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-17 18:41:20 +00:00
fix update cache
This commit is contained in:
parent
864d87697c
commit
700d5374ed
@ -12,22 +12,47 @@ export default function LanguageSelector({
|
|||||||
onChange: (value: string | null) => void;
|
onChange: (value: string | null) => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
options={languageOptions}
|
size="small"
|
||||||
getOptionLabel={(option) => `${option.name} (${option.code})`}
|
options={languageOptions}
|
||||||
value={languageOptions.find((opt) => opt.code === value) || null}
|
getOptionLabel={(option) => `${option.name} (${option.code})`}
|
||||||
onChange={(event, newValue) => onChange(newValue?.code || null)}
|
value={languageOptions.find((opt) => opt.code === value) || null}
|
||||||
renderInput={(params) => <TextField {...params} label="Subtitle Language" />}
|
onChange={(event, newValue) => onChange(newValue?.code || null)}
|
||||||
isOptionEqualToValue={(option, val) => option.code === val.code}
|
renderInput={(params) => (
|
||||||
sx={{ width: 300 }}
|
<TextField
|
||||||
slotProps={{
|
required
|
||||||
|
{...params}
|
||||||
|
label="Subtitle Language"
|
||||||
|
sx={{
|
||||||
|
fontSize: '1rem', // Input text size
|
||||||
|
'& .MuiInputBase-input': {
|
||||||
|
fontSize: '1rem', // Inner input
|
||||||
|
},
|
||||||
|
'& .MuiInputLabel-root': {
|
||||||
|
fontSize: '0.75rem', // Label text
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
isOptionEqualToValue={(option, val) => option.code === val.code}
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '1rem', // affects root font size
|
||||||
|
'& .MuiAutocomplete-input': {
|
||||||
|
fontSize: '1rem',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
popper: {
|
popper: {
|
||||||
sx: {
|
sx: {
|
||||||
zIndex: 999991, // Must be higher than Dialog's default zIndex (1300)
|
zIndex: 999991,
|
||||||
|
'& .MuiAutocomplete-paper': {
|
||||||
|
fontSize: '1rem', // dropdown font size
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
QortalGetMetadata,
|
QortalGetMetadata,
|
||||||
QortalMetadata,
|
QortalMetadata,
|
||||||
@ -9,6 +9,7 @@ import {
|
|||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
ButtonBase,
|
ButtonBase,
|
||||||
|
Card,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -17,10 +18,12 @@ import {
|
|||||||
Fade,
|
Fade,
|
||||||
IconButton,
|
IconButton,
|
||||||
Popover,
|
Popover,
|
||||||
|
Tab,
|
||||||
|
Tabs,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from "@mui/icons-material/Check";
|
||||||
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
|
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||||
import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos";
|
import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos";
|
||||||
import ModeEditIcon from "@mui/icons-material/ModeEdit";
|
import ModeEditIcon from "@mui/icons-material/ModeEdit";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
@ -39,6 +42,7 @@ import { fileToBase64, objectToBase64 } from "../../utils/base64";
|
|||||||
import { ResourceToPublish } from "../../types/qortalRequests/types";
|
import { ResourceToPublish } from "../../types/qortalRequests/types";
|
||||||
import { useListReturn } from "../../hooks/useListData";
|
import { useListReturn } from "../../hooks/useListData";
|
||||||
import { usePublish } from "../../hooks/usePublish";
|
import { usePublish } from "../../hooks/usePublish";
|
||||||
|
import { Spacer } from "../../common/Spacer";
|
||||||
interface SubtitleManagerProps {
|
interface SubtitleManagerProps {
|
||||||
qortalMetadata: QortalGetMetadata;
|
qortalMetadata: QortalGetMetadata;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
@ -67,6 +71,14 @@ export const languageOptions = ISO6391.getAllCodes().map((code) => ({
|
|||||||
name: ISO6391.getName(code),
|
name: ISO6391.getName(code),
|
||||||
nativeName: ISO6391.getNativeName(code),
|
nativeName: ISO6391.getNativeName(code),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function a11yProps(index: number) {
|
||||||
|
return {
|
||||||
|
id: `subtitle-tab-${index}`,
|
||||||
|
"aria-controls": `subtitle-tabpanel-${index}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const SubtitleManagerComponent = ({
|
const SubtitleManagerComponent = ({
|
||||||
qortalMetadata,
|
qortalMetadata,
|
||||||
open,
|
open,
|
||||||
@ -76,13 +88,18 @@ const SubtitleManagerComponent = ({
|
|||||||
currentSubTrack,
|
currentSubTrack,
|
||||||
}: SubtitleManagerProps) => {
|
}: SubtitleManagerProps) => {
|
||||||
const [mode, setMode] = useState(1);
|
const [mode, setMode] = useState(1);
|
||||||
|
const [isOpenPublish, setIsOpenPublish] = useState(false);
|
||||||
const { lists, identifierOperations, auth } = useGlobal();
|
const { lists, identifierOperations, auth } = useGlobal();
|
||||||
const { fetchResources } = useResources();
|
const { fetchResources } = useResources();
|
||||||
// const [subtitles, setSubtitles] = useState([])
|
// const [subtitles, setSubtitles] = useState([])
|
||||||
const subtitles = useListReturn(
|
const subtitles = useListReturn(
|
||||||
`subs-${qortalMetadata?.service}-${qortalMetadata?.name}-${qortalMetadata?.identifier}`
|
`subs-${qortalMetadata?.service}-${qortalMetadata?.name}-${qortalMetadata?.identifier}`
|
||||||
);
|
);
|
||||||
|
console.log('subtitles222', subtitles)
|
||||||
|
const mySubtitles = useMemo(()=> {
|
||||||
|
if(!auth?.name)return []
|
||||||
|
return subtitles?.filter((sub)=> sub.name === auth?.name)
|
||||||
|
}, [subtitles, auth?.name])
|
||||||
console.log("subtitles222", subtitles);
|
console.log("subtitles222", subtitles);
|
||||||
const getPublishedSubtitles = useCallback(async () => {
|
const getPublishedSubtitles = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@ -193,93 +210,95 @@ const SubtitleManagerComponent = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSelectHandler = (sub: SubtitlePublishedData) => {
|
const onSelectHandler = (sub: SubtitlePublishedData) => {
|
||||||
console.log('onSelectHandler')
|
console.log("onSelectHandler");
|
||||||
onSelect(sub);
|
onSelect(sub);
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<>
|
||||||
open={!!open}
|
<Popover
|
||||||
anchorEl={subtitleBtnRef.current}
|
open={!!open}
|
||||||
onClose={handleClose}
|
anchorEl={subtitleBtnRef.current}
|
||||||
slots={{
|
onClose={handleClose}
|
||||||
transition: Fade,
|
slots={{
|
||||||
}}
|
transition: Fade,
|
||||||
slotProps={{
|
}}
|
||||||
transition: {
|
slotProps={{
|
||||||
timeout: 200,
|
transition: {
|
||||||
},
|
timeout: 200,
|
||||||
paper: {
|
|
||||||
sx: {
|
|
||||||
bgcolor: alpha("#181818", 0.98),
|
|
||||||
color: "white",
|
|
||||||
opacity: 0.9,
|
|
||||||
borderRadius: 2,
|
|
||||||
boxShadow: 5,
|
|
||||||
p: 1,
|
|
||||||
minWidth: 200,
|
|
||||||
},
|
},
|
||||||
},
|
paper: {
|
||||||
}}
|
sx: {
|
||||||
anchorOrigin={{
|
bgcolor: alpha("#181818", 0.98),
|
||||||
vertical: "top",
|
color: "white",
|
||||||
horizontal: "center",
|
opacity: 0.9,
|
||||||
}}
|
borderRadius: 2,
|
||||||
transformOrigin={{
|
boxShadow: 5,
|
||||||
vertical: "bottom",
|
p: 1,
|
||||||
horizontal: "center",
|
minWidth: 200,
|
||||||
}}
|
},
|
||||||
>
|
},
|
||||||
<Box
|
}}
|
||||||
sx={{
|
anchorOrigin={{
|
||||||
padding: "5px 0px 10px 0px",
|
vertical: "top",
|
||||||
display: "flex",
|
horizontal: "center",
|
||||||
gap: "10px",
|
}}
|
||||||
width: "100%",
|
transformOrigin={{
|
||||||
|
vertical: "bottom",
|
||||||
|
horizontal: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ButtonBase onClick={onBack}>
|
<Box
|
||||||
<ArrowBackIosIcon
|
|
||||||
sx={{
|
|
||||||
fontSize: "1.15em",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase>
|
|
||||||
<Typography
|
|
||||||
onClick={onBack}
|
|
||||||
sx={{
|
|
||||||
fontSize: "0.85rem",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Subtitles
|
|
||||||
</Typography>
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase
|
|
||||||
sx={{
|
sx={{
|
||||||
marginLeft: "auto",
|
padding: "5px 0px 10px 0px",
|
||||||
|
display: "flex",
|
||||||
|
gap: "10px",
|
||||||
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ModeEditIcon
|
<ButtonBase onClick={onBack}>
|
||||||
|
<ArrowBackIosIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: "1.15em",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase>
|
||||||
|
<Typography
|
||||||
|
onClick={onBack}
|
||||||
|
sx={{
|
||||||
|
fontSize: "0.85rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Subtitles
|
||||||
|
</Typography>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "1.15rem",
|
marginLeft: "auto",
|
||||||
}}
|
}}
|
||||||
|
onClick={() => setIsOpenPublish(true)}
|
||||||
|
>
|
||||||
|
<ModeEditIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: "1.15rem",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
</Box>
|
||||||
|
<Divider />
|
||||||
|
{mode === 1 && (
|
||||||
|
<PublisherSubtitles
|
||||||
|
subtitles={subtitles}
|
||||||
|
publisherName={qortalMetadata.name}
|
||||||
|
setMode={setMode}
|
||||||
|
onSelect={onSelectHandler}
|
||||||
|
onBack={onBack}
|
||||||
|
currentSubTrack={currentSubTrack}
|
||||||
/>
|
/>
|
||||||
</ButtonBase>
|
)}
|
||||||
</Box>
|
{/* <Box>
|
||||||
<Divider />
|
|
||||||
{mode === 1 && (
|
|
||||||
<PublisherSubtitles
|
|
||||||
subtitles={subtitles}
|
|
||||||
publisherName={qortalMetadata.name}
|
|
||||||
setMode={setMode}
|
|
||||||
onSelect={onSelectHandler}
|
|
||||||
onBack={onBack}
|
|
||||||
currentSubTrack={currentSubTrack}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{/* <Box>
|
|
||||||
{[
|
{[
|
||||||
'Ambient mode',
|
'Ambient mode',
|
||||||
'Annotations',
|
'Annotations',
|
||||||
@ -303,7 +322,15 @@ const SubtitleManagerComponent = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
))}
|
))}
|
||||||
</Box> */}
|
</Box> */}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
|
<PublishSubtitles
|
||||||
|
isOpen={isOpenPublish}
|
||||||
|
setIsOpen={setIsOpenPublish}
|
||||||
|
publishHandler={publishHandler}
|
||||||
|
mySubtitles={mySubtitles}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
// <Dialog
|
// <Dialog
|
||||||
// open={!!open}
|
// open={!!open}
|
||||||
// fullWidth={true}
|
// fullWidth={true}
|
||||||
@ -374,7 +401,7 @@ interface PublisherSubtitlesProps {
|
|||||||
setMode: (val: number) => void;
|
setMode: (val: number) => void;
|
||||||
onSelect: (subtitle: any) => void;
|
onSelect: (subtitle: any) => void;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
currentSubTrack: string | null
|
currentSubTrack: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PublisherSubtitles = ({
|
const PublisherSubtitles = ({
|
||||||
@ -383,7 +410,7 @@ const PublisherSubtitles = ({
|
|||||||
setMode,
|
setMode,
|
||||||
onSelect,
|
onSelect,
|
||||||
onBack,
|
onBack,
|
||||||
currentSubTrack
|
currentSubTrack,
|
||||||
}: PublisherSubtitlesProps) => {
|
}: PublisherSubtitlesProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -403,11 +430,20 @@ const PublisherSubtitles = ({
|
|||||||
|
|
||||||
interface PublishSubtitlesProps {
|
interface PublishSubtitlesProps {
|
||||||
publishHandler: (subs: Subtitle[]) => void;
|
publishHandler: (subs: Subtitle[]) => void;
|
||||||
|
isOpen: boolean;
|
||||||
|
setIsOpen: (val: boolean) => void;
|
||||||
|
mySubtitles: QortalGetMetadata[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const PublishSubtitles = ({ publishHandler }: PublishSubtitlesProps) => {
|
const PublishSubtitles = ({
|
||||||
|
publishHandler,
|
||||||
|
isOpen,
|
||||||
|
setIsOpen,
|
||||||
|
mySubtitles
|
||||||
|
}: PublishSubtitlesProps) => {
|
||||||
const [language, setLanguage] = useState<null | string>(null);
|
const [language, setLanguage] = useState<null | string>(null);
|
||||||
const [subtitles, setSubtitles] = useState<Subtitle[]>([]);
|
const [subtitles, setSubtitles] = useState<Subtitle[]>([]);
|
||||||
|
const {lists} = useGlobal()
|
||||||
const onDrop = useCallback(async (acceptedFiles: File[]) => {
|
const onDrop = useCallback(async (acceptedFiles: File[]) => {
|
||||||
const newSubtitles: Subtitle[] = [];
|
const newSubtitles: Subtitle[] = [];
|
||||||
for (const file of acceptedFiles) {
|
for (const file of acceptedFiles) {
|
||||||
@ -457,16 +493,74 @@ const PublishSubtitles = ({ publishHandler }: PublishSubtitlesProps) => {
|
|||||||
};
|
};
|
||||||
console.log("subtitles", subtitles);
|
console.log("subtitles", subtitles);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [value, setValue] = useState(0);
|
||||||
|
|
||||||
|
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
||||||
|
setValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = useCallback(async (sub: QortalGetMetadata)=> {
|
||||||
|
try {
|
||||||
|
await lists.deleteResource([
|
||||||
|
sub
|
||||||
|
])
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Dialog
|
||||||
|
open={isOpen}
|
||||||
|
fullWidth={true}
|
||||||
|
maxWidth={"md"}
|
||||||
|
sx={{
|
||||||
|
zIndex: 999990,
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
paper: {
|
||||||
|
elevation: 0,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle>My Subtitles</DialogTitle>
|
||||||
|
<IconButton
|
||||||
|
aria-label="close"
|
||||||
|
onClick={handleClose}
|
||||||
|
sx={(theme) => ({
|
||||||
|
position: "absolute",
|
||||||
|
right: 8,
|
||||||
|
top: 8,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Box
|
<Box sx={{ width: "100%" }}>
|
||||||
|
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||||||
|
<Tabs
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
aria-label="basic tabs example"
|
||||||
|
>
|
||||||
|
<Tab label="New" {...a11yProps(0)} />
|
||||||
|
<Tab label="Existing" {...a11yProps(1)} />
|
||||||
|
</Tabs>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Spacer height="25px" />
|
||||||
|
{value === 0 && (
|
||||||
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: "20px",
|
gap: "20px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
alignItems: "flex-start",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box {...getRootProps()}>
|
<Box {...getRootProps()}>
|
||||||
@ -483,17 +577,81 @@ const PublishSubtitles = ({ publishHandler }: PublishSubtitlesProps) => {
|
|||||||
</Box>
|
</Box>
|
||||||
{subtitles?.map((sub, i) => {
|
{subtitles?.map((sub, i) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Card
|
||||||
|
sx={{
|
||||||
|
padding: "10px",
|
||||||
|
width: "500px",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{sub.filename}
|
||||||
|
</Typography>
|
||||||
|
<Spacer height="10px" />
|
||||||
<LanguageSelect
|
<LanguageSelect
|
||||||
value={sub.language}
|
value={sub.language}
|
||||||
onChange={(val: string | null) =>
|
onChange={(val: string | null) =>
|
||||||
onChangeValue("language", val, i)
|
onChangeValue("language", val, i)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
<Spacer height="10px" />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setSubtitles((prev) => {
|
||||||
|
const newSubtitles = [...prev];
|
||||||
|
newSubtitles.splice(i, 1); // Remove 1 item at index i
|
||||||
|
return newSubtitles;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
remove
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
|
{value === 1 && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "20px",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
{mySubtitles?.map((sub, i) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
sx={{
|
||||||
|
padding: "10px",
|
||||||
|
width: "500px",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MySubtitle onDelete={onDelete} sub={sub} />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
@ -501,46 +659,87 @@ const PublishSubtitles = ({ publishHandler }: PublishSubtitlesProps) => {
|
|||||||
// disabled={disableButton}
|
// disabled={disableButton}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
>
|
>
|
||||||
Publish index
|
Publish
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface SubProps {
|
interface SubProps {
|
||||||
sub: QortalGetMetadata;
|
sub: QortalGetMetadata;
|
||||||
onSelect: (subtitle: Subtitle) => void;
|
onSelect: (subtitle: Subtitle) => void;
|
||||||
currentSubtrack: null | string
|
currentSubtrack: null | string;
|
||||||
}
|
}
|
||||||
const Subtitle = ({ sub, onSelect, currentSubtrack }: SubProps) => {
|
const Subtitle = ({ sub, onSelect, currentSubtrack }: SubProps) => {
|
||||||
const { resource, isLoading } = usePublish(2, "JSON", sub);
|
const { resource, isLoading } = usePublish(2, "JSON", sub);
|
||||||
console.log("resource", resource);
|
console.log("resource", resource);
|
||||||
const isSelected = currentSubtrack === resource?.data?.language
|
const isSelected = currentSubtrack === resource?.data?.language;
|
||||||
return (
|
return (
|
||||||
<ButtonBase onClick={() => onSelect(isSelected ? null : resource?.data)} sx={{
|
<ButtonBase
|
||||||
|
onClick={() => onSelect(isSelected ? null : resource?.data)}
|
||||||
|
sx={{
|
||||||
px: 2,
|
px: 2,
|
||||||
py: 1,
|
py: 1,
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||||
},
|
},
|
||||||
width: '100%',
|
width: "100%",
|
||||||
justifyContent: 'space-between'
|
justifyContent: "space-between",
|
||||||
}}>
|
}}
|
||||||
<Typography
|
|
||||||
|
|
||||||
|
|
||||||
>
|
>
|
||||||
{resource?.data?.language}
|
<Typography>{resource?.data?.language}</Typography>
|
||||||
</Typography>
|
{isSelected ? <CheckIcon /> : <ArrowForwardIosIcon />}
|
||||||
{isSelected ? (
|
|
||||||
<CheckIcon />
|
|
||||||
) : (
|
|
||||||
<ArrowForwardIosIcon />
|
|
||||||
)}
|
|
||||||
|
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface MySubtitleProps {
|
||||||
|
sub: QortalGetMetadata;
|
||||||
|
onDelete: (subtitle: QortalGetMetadata) => void;
|
||||||
|
}
|
||||||
|
const MySubtitle = ({ sub, onDelete }: MySubtitleProps) => {
|
||||||
|
const { resource, isLoading } = usePublish(2, "JSON", sub);
|
||||||
|
console.log("resource", resource);
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
sx={{
|
||||||
|
padding: "10px",
|
||||||
|
width: "500px",
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{resource?.data?.filename}
|
||||||
|
</Typography>
|
||||||
|
<Spacer height="10px" />
|
||||||
|
<Typography sx={{
|
||||||
|
fontSize: '1rem'
|
||||||
|
}}>{resource?.data?.language}</Typography>
|
||||||
|
<Spacer height="10px" />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => onDelete(sub)}
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
>
|
||||||
|
delete
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const SubtitleManager = React.memo(SubtitleManagerComponent);
|
export const SubtitleManager = React.memo(SubtitleManagerComponent);
|
||||||
|
@ -5,5 +5,12 @@ import { QortalGetMetadata } from "../types/interfaces/resources";
|
|||||||
|
|
||||||
export function useListReturn(listName: string): QortalGetMetadata[] {
|
export function useListReturn(listName: string): QortalGetMetadata[] {
|
||||||
const list = useListStore((state) => state.lists[listName]?.items) || [];
|
const list = useListStore((state) => state.lists[listName]?.items) || [];
|
||||||
return list
|
const filterOutDeletedResources = useCacheStore((s) => s.filterOutDeletedResources);
|
||||||
|
const deletedResources = useCacheStore((s) => s.deletedResources);
|
||||||
|
const temporaryResources = useCacheStore().getTemporaryResources(listName)
|
||||||
|
|
||||||
|
const listToDisplay = useMemo(()=> {
|
||||||
|
return filterOutDeletedResources([...temporaryResources, ...(list || [])])
|
||||||
|
}, [list, listName, deletedResources, temporaryResources])
|
||||||
|
return listToDisplay
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import { QortalGetMetadata, QortalMetadata } from "../types/interfaces/resources
|
|||||||
import { base64ToObject, retryTransaction } from "../utils/publish";
|
import { base64ToObject, retryTransaction } from "../utils/publish";
|
||||||
import { useGlobal } from "../context/GlobalProvider";
|
import { useGlobal } from "../context/GlobalProvider";
|
||||||
import { ReturnType } from "../components/ResourceList/ResourceListDisplay";
|
import { ReturnType } from "../components/ResourceList/ResourceListDisplay";
|
||||||
|
import { useCacheStore } from "../state/cache";
|
||||||
|
|
||||||
const STORAGE_EXPIRY_DURATION = 5 * 60 * 1000;
|
|
||||||
interface StoredPublish {
|
interface StoredPublish {
|
||||||
qortalMetadata: QortalMetadata;
|
qortalMetadata: QortalMetadata;
|
||||||
data: any;
|
data: any;
|
||||||
@ -68,6 +68,8 @@ interface StoredPublish {
|
|||||||
const publish = usePublishStore().getPublish(metadata || null, true);
|
const publish = usePublishStore().getPublish(metadata || null, true);
|
||||||
const setPublish = usePublishStore((state)=> state.setPublish)
|
const setPublish = usePublishStore((state)=> state.setPublish)
|
||||||
const getPublish = usePublishStore(state=> state.getPublish)
|
const getPublish = usePublishStore(state=> state.getPublish)
|
||||||
|
const setResourceCache = useCacheStore((s) => s.setResourceCache);
|
||||||
|
const markResourceAsDeleted = useCacheStore((s) => s.markResourceAsDeleted);
|
||||||
|
|
||||||
const [hasResource, setHasResource] = useState<boolean | null>(null);
|
const [hasResource, setHasResource] = useState<boolean | null>(null);
|
||||||
const fetchRawData = useCallback(async (item: QortalGetMetadata) => {
|
const fetchRawData = useCallback(async (item: QortalGetMetadata) => {
|
||||||
@ -85,30 +87,7 @@ interface StoredPublish {
|
|||||||
return `qortal_publish_${username}_${appNameHashed}`;
|
return `qortal_publish_${username}_${appNameHashed}`;
|
||||||
}, [username, appNameHashed]);
|
}, [username, appNameHashed]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!username || !appNameHashed) return;
|
|
||||||
|
|
||||||
const storageKey = getStorageKey();
|
|
||||||
if (!storageKey) return;
|
|
||||||
|
|
||||||
const storedData: StoredPublish[] = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
|
||||||
|
|
||||||
if (Array.isArray(storedData) && storedData.length > 0) {
|
|
||||||
const now = Date.now();
|
|
||||||
const validPublishes = storedData.filter((item) => now - item.timestamp < STORAGE_EXPIRY_DURATION);
|
|
||||||
|
|
||||||
// ✅ Re-populate the Zustand store only with recent publishes
|
|
||||||
validPublishes.forEach((publishData) => {
|
|
||||||
setPublish(publishData.qortalMetadata, {
|
|
||||||
qortalMetadata: publishData.qortalMetadata,
|
|
||||||
data: publishData.data
|
|
||||||
}, Date.now() - publishData.timestamp);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ✅ Re-store only valid (non-expired) publishes
|
|
||||||
localStorage.setItem(storageKey, JSON.stringify(validPublishes));
|
|
||||||
}
|
|
||||||
}, [username, appNameHashed, getStorageKey, setPublish]);
|
|
||||||
|
|
||||||
const fetchPublish = useCallback(
|
const fetchPublish = useCallback(
|
||||||
async (
|
async (
|
||||||
@ -121,8 +100,9 @@ interface StoredPublish {
|
|||||||
if (metadata) {
|
if (metadata) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
}
|
}
|
||||||
const hasCache = getPublish(metadataProp)
|
|
||||||
|
const hasCache = getPublish(metadataProp)
|
||||||
|
|
||||||
if(hasCache){
|
if(hasCache){
|
||||||
if(hasCache?.qortalMetadata.size === 32){
|
if(hasCache?.qortalMetadata.size === 32){
|
||||||
if(metadata){
|
if(metadata){
|
||||||
@ -139,6 +119,7 @@ interface StoredPublish {
|
|||||||
if(metadata){
|
if(metadata){
|
||||||
setHasResource(true)
|
setHasResource(true)
|
||||||
setError(null)
|
setError(null)
|
||||||
|
setPublish(metadataProp, hasCache);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
resource: hasCache,
|
resource: hasCache,
|
||||||
@ -240,30 +221,11 @@ interface StoredPublish {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (res?.signature) {
|
if (res?.signature) {
|
||||||
const storageKey = getStorageKey();
|
|
||||||
if (storageKey) {
|
|
||||||
const existingPublishes = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
|
||||||
|
|
||||||
// Remove any previous entries for the same identifier
|
|
||||||
const updatedPublishes = existingPublishes.filter(
|
|
||||||
(item: StoredPublish) => item.qortalMetadata.identifier !== publish.identifier && item.qortalMetadata.service !== publish.service && item.qortalMetadata.name !== publish.name
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the new one with timestamp
|
|
||||||
updatedPublishes.push({ qortalMetadata: {
|
|
||||||
...publish,
|
|
||||||
created: Date.now(),
|
|
||||||
updated: Date.now(),
|
|
||||||
size: 32
|
|
||||||
}, data: "RA==", timestamp: Date.now() });
|
|
||||||
|
|
||||||
// Save back to storage
|
|
||||||
localStorage.setItem(storageKey, JSON.stringify(updatedPublishes));
|
|
||||||
}
|
|
||||||
setPublish(publish, null);
|
setPublish(publish, null);
|
||||||
setError(null)
|
setError(null)
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
setHasResource(false)
|
setHasResource(false)
|
||||||
|
markResourceAsDeleted(publish)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, [getStorageKey]);
|
}, [getStorageKey]);
|
||||||
@ -279,27 +241,16 @@ interface StoredPublish {
|
|||||||
updated: Date.now(),
|
updated: Date.now(),
|
||||||
size: 100
|
size: 100
|
||||||
}, data});
|
}, data});
|
||||||
|
setResourceCache(
|
||||||
const storageKey = getStorageKey();
|
`${publish?.service}-${publish?.name}-${publish?.identifier}`,
|
||||||
if (storageKey) {
|
{qortalMetadata: {
|
||||||
const existingPublishes = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
...publish,
|
||||||
|
|
||||||
// Remove any previous entries for the same identifier
|
|
||||||
const updatedPublishes = existingPublishes.filter(
|
|
||||||
(item: StoredPublish) => item.qortalMetadata.identifier !== publish.identifier && item.qortalMetadata.service !== publish.service && item.qortalMetadata.name !== publish.name
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the new one with timestamp
|
|
||||||
updatedPublishes.push({ qortalMetadata: {
|
|
||||||
...publish,
|
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
updated: Date.now(),
|
updated: Date.now(),
|
||||||
size: 100
|
size: 100
|
||||||
}, data, timestamp: Date.now() });
|
}, data}
|
||||||
|
);
|
||||||
|
|
||||||
// Save back to storage
|
|
||||||
localStorage.setItem(storageKey, JSON.stringify(updatedPublishes));
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [getStorageKey, setPublish]);
|
}, [getStorageKey, setPublish]);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import { base64ToUint8Array, uint8ArrayToObject } from "../utils/base64";
|
|||||||
import { retryTransaction } from "../utils/publish";
|
import { retryTransaction } from "../utils/publish";
|
||||||
import { ReturnType } from "../components/ResourceList/ResourceListDisplay";
|
import { ReturnType } from "../components/ResourceList/ResourceListDisplay";
|
||||||
import { useListStore } from "../state/lists";
|
import { useListStore } from "../state/lists";
|
||||||
|
import { usePublishStore } from "../state/publishes";
|
||||||
|
|
||||||
export const requestQueueProductPublishes = new RequestQueueWithPromise(20);
|
export const requestQueueProductPublishes = new RequestQueueWithPromise(20);
|
||||||
export const requestQueueProductPublishesBackup = new RequestQueueWithPromise(
|
export const requestQueueProductPublishesBackup = new RequestQueueWithPromise(
|
||||||
@ -20,7 +21,7 @@ export interface Resource {
|
|||||||
qortalMetadata: QortalMetadata;
|
qortalMetadata: QortalMetadata;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
export const useResources = (retryAttempts: number = 2) => {
|
export const useResources = (retryAttempts: number = 2, maxSize = 5242880) => {
|
||||||
const setSearchCache = useCacheStore((s) => s.setSearchCache);
|
const setSearchCache = useCacheStore((s) => s.setSearchCache);
|
||||||
const getSearchCache = useCacheStore((s) => s.getSearchCache);
|
const getSearchCache = useCacheStore((s) => s.getSearchCache);
|
||||||
const getResourceCache = useCacheStore((s) => s.getResourceCache);
|
const getResourceCache = useCacheStore((s) => s.getResourceCache);
|
||||||
@ -29,6 +30,7 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
const markResourceAsDeleted = useCacheStore((s) => s.markResourceAsDeleted);
|
const markResourceAsDeleted = useCacheStore((s) => s.markResourceAsDeleted);
|
||||||
const setSearchParamsForList = useCacheStore((s) => s.setSearchParamsForList);
|
const setSearchParamsForList = useCacheStore((s) => s.setSearchParamsForList);
|
||||||
const addList = useListStore((s) => s.addList);
|
const addList = useListStore((s) => s.addList);
|
||||||
|
const setPublish = usePublishStore((state)=> state.setPublish)
|
||||||
|
|
||||||
const deleteList = useListStore(state => state.deleteList)
|
const deleteList = useListStore(state => state.deleteList)
|
||||||
const requestControllers = new Map<string, AbortController>();
|
const requestControllers = new Map<string, AbortController>();
|
||||||
@ -240,7 +242,7 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
responseData = response;
|
responseData = response;
|
||||||
const validResults = responseData.filter((item) => item.size !== 32);
|
const validResults = responseData.filter((item) => item.size !== 32 && item.size < maxSize);
|
||||||
console.log('validResults', validResults)
|
console.log('validResults', validResults)
|
||||||
filteredResults = [...filteredResults, ...validResults];
|
filteredResults = [...filteredResults, ...validResults];
|
||||||
|
|
||||||
@ -258,7 +260,6 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
delete copyParams.after
|
delete copyParams.after
|
||||||
delete copyParams.before
|
delete copyParams.before
|
||||||
delete copyParams.offset
|
delete copyParams.offset
|
||||||
console.log('listName2', listName, filteredResults)
|
|
||||||
setSearchCache(listName, cacheKey, filteredResults, cancelRequests ? JSON.stringify(copyParams) : null);
|
setSearchCache(listName, cacheKey, filteredResults, cancelRequests ? JSON.stringify(copyParams) : null);
|
||||||
fetchDataFromResults(filteredResults, returnType);
|
fetchDataFromResults(filteredResults, returnType);
|
||||||
|
|
||||||
@ -309,7 +310,7 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
|
|
||||||
const addNewResources = useCallback(
|
const addNewResources = useCallback(
|
||||||
(listName: string, resources: Resource[]) => {
|
(listName: string, resources: Resource[]) => {
|
||||||
|
console.log('resources1212', resources)
|
||||||
addTemporaryResource(
|
addTemporaryResource(
|
||||||
listName,
|
listName,
|
||||||
resources.map((item) => item.qortalMetadata)
|
resources.map((item) => item.qortalMetadata)
|
||||||
@ -319,6 +320,7 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
`${temporaryResource?.qortalMetadata?.service}-${temporaryResource?.qortalMetadata?.name}-${temporaryResource?.qortalMetadata?.identifier}`,
|
`${temporaryResource?.qortalMetadata?.service}-${temporaryResource?.qortalMetadata?.name}-${temporaryResource?.qortalMetadata?.identifier}`,
|
||||||
temporaryResource
|
temporaryResource
|
||||||
);
|
);
|
||||||
|
setPublish(temporaryResource?.qortalMetadata, temporaryResource);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
@ -330,6 +332,7 @@ export const useResources = (retryAttempts: number = 2) => {
|
|||||||
`${temporaryResource?.qortalMetadata?.service}-${temporaryResource?.qortalMetadata?.name}-${temporaryResource?.qortalMetadata?.identifier}`,
|
`${temporaryResource?.qortalMetadata?.service}-${temporaryResource?.qortalMetadata?.name}-${temporaryResource?.qortalMetadata?.identifier}`,
|
||||||
temporaryResource
|
temporaryResource
|
||||||
);
|
);
|
||||||
|
setPublish(temporaryResource?.qortalMetadata, temporaryResource);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user