fix: Language cache sight
This commit is contained in:
178
src/shared/modals/SelectMediaDialog/index.tsx
Normal file
178
src/shared/modals/SelectMediaDialog/index.tsx
Normal file
@ -0,0 +1,178 @@
|
||||
import { articlesStore, authStore, Language, mediaStore } from "@shared";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Button,
|
||||
TextField,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemText,
|
||||
Paper,
|
||||
Box,
|
||||
Typography,
|
||||
InputAdornment,
|
||||
} from "@mui/material";
|
||||
import { ImagePlus, Search } from "lucide-react";
|
||||
import { ReactMarkdownComponent, MediaViewer } from "@widgets";
|
||||
|
||||
interface SelectMediaDialogProps {
|
||||
open: boolean; // Corrected prop name
|
||||
onClose: () => void;
|
||||
onSelectMedia: (mediaId: string) => void; // Renamed from onSelectArticle
|
||||
linkedMediaIds?: string[]; // Renamed from linkedArticleIds, assuming it refers to media already in use
|
||||
}
|
||||
|
||||
export const SelectMediaDialog = observer(
|
||||
({
|
||||
open, // Corrected prop name
|
||||
onClose,
|
||||
onSelectMedia, // Renamed prop
|
||||
linkedMediaIds = [], // Default to empty array if not provided, renamed
|
||||
}: SelectMediaDialogProps) => {
|
||||
const { media, getMedia } = mediaStore; // Confirmed: using mediaStore for media
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [hoveredMediaId, setHoveredMediaId] = useState<string | null>(null);
|
||||
const hoverTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Fetch media on component mount
|
||||
useEffect(() => {
|
||||
getMedia();
|
||||
}, [getMedia]); // getMedia should be a dependency to avoid lint warnings if it's not stable
|
||||
|
||||
// Keyboard event listener for "Enter" key to select hovered media
|
||||
useEffect(() => {
|
||||
const handleKeyPress = (event: KeyboardEvent) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault(); // Prevent browser default action (e.g., form submission)
|
||||
|
||||
if (hoveredMediaId) {
|
||||
onSelectMedia(hoveredMediaId); // Call onSelectMedia
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyPress);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyPress);
|
||||
};
|
||||
}, [hoveredMediaId, onSelectMedia, onClose]); // Dependencies for keyboard listener
|
||||
|
||||
// Effect for handling hover timeout (if you want to clear the preview after a delay)
|
||||
// Based on the original code, it seemed like you wanted a delay for showing,
|
||||
// but typically for a preview, it's immediate on hover and cleared on mouse leave.
|
||||
// I've removed the 5-second timeout for setting the ID as it's counter-intuitive for a live preview.
|
||||
// If you intend for the preview to disappear after a short while *after* the mouse leaves,
|
||||
// you would implement a mouseleave timer. For now, it will clear on mouseleave.
|
||||
|
||||
const handleMouseEnter = (mediaId: string) => {
|
||||
if (hoverTimerRef.current) {
|
||||
clearTimeout(hoverTimerRef.current);
|
||||
}
|
||||
setHoveredMediaId(mediaId);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
// You can add a small delay here if you want the preview to linger for a moment
|
||||
// before disappearing, e.g., setTimeout(() => setHoveredMediaId(null), 200);
|
||||
setHoveredMediaId(null);
|
||||
};
|
||||
|
||||
const filteredMedia = media
|
||||
.filter((mediaItem) => !linkedMediaIds.includes(mediaItem.id)) // Use mediaItem to avoid name collision
|
||||
.filter((mediaItem) =>
|
||||
mediaItem.media_name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// Find the currently hovered media object for MediaViewer
|
||||
const currentHoveredMedia = hoveredMediaId
|
||||
? media.find((m) => m.id === hoveredMediaId)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} maxWidth="lg" fullWidth>
|
||||
<DialogTitle>Выберите существующее медиа</DialogTitle>
|
||||
<DialogContent
|
||||
className="flex gap-4"
|
||||
dividers // Adds a divider below the title and above the actions
|
||||
sx={{ height: "600px", display: "flex", flexDirection: "row" }} // Fixed height for DialogContent
|
||||
>
|
||||
<Paper className="w-[66%] flex flex-col" sx={{ p: 2 }}>
|
||||
{" "}
|
||||
{/* Added padding for consistency */}
|
||||
<TextField
|
||||
fullWidth
|
||||
placeholder="Поиск медиа..." // Changed placeholder for clarity
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
sx={{ mb: 2, mt: 1 }}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<Search size={20} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<List sx={{ flexGrow: 1, overflowY: "auto" }}>
|
||||
{filteredMedia.length > 0 ? (
|
||||
filteredMedia.map(
|
||||
(
|
||||
mediaItem // Use mediaItem to avoid confusion
|
||||
) => (
|
||||
<ListItemButton
|
||||
key={mediaItem.id}
|
||||
onClick={() => onSelectMedia(mediaItem.id)} // Call onSelectMedia
|
||||
onMouseEnter={() => handleMouseEnter(mediaItem.id)}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
sx={{
|
||||
borderRadius: 1,
|
||||
mb: 0.5,
|
||||
"&:hover": {
|
||||
backgroundColor: "action.hover",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemText primary={mediaItem.media_name} />
|
||||
</ListItemButton>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<Typography
|
||||
sx={{ mt: 2, textAlign: "center" }}
|
||||
color="text.secondary"
|
||||
>
|
||||
Медиа не найдено или все медиа уже прикреплены.
|
||||
</Typography>
|
||||
)}
|
||||
</List>
|
||||
</Paper>
|
||||
{currentHoveredMedia ? ( // Only render MediaViewer if currentHoveredMedia is found
|
||||
<Paper className="w-[33%] h-[100%] flex justify-center items-center">
|
||||
<MediaViewer
|
||||
media={{
|
||||
id: currentHoveredMedia.id,
|
||||
media_type: currentHoveredMedia.media_type ?? 1, // Provide a default if media_type can be undefined
|
||||
filename: currentHoveredMedia.filename,
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
) : (
|
||||
<Paper className="w-[33%] h-[100%] flex justify-center items-center">
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Наведите на медиа в списке для предпросмотра.
|
||||
</Typography>
|
||||
</Paper>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>Отмена</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
);
|
Reference in New Issue
Block a user