This commit is contained in:
Brage 2024-03-30 14:25:59 +01:00
parent 98ca3e239f
commit b9a10e7585
3 changed files with 128 additions and 0 deletions

View File

@ -0,0 +1,64 @@
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../store";
import { setContextMenuVisible } from "../store/context-menu-slice";
import { Box, Typography, useTheme } from "@mui/material";
export interface ContextMenuItem {
actionIndex: number,
icon: JSX.Element | null,
text: string
}
type NullableContextMenuActionEvent<T> = ContextMenuActionEvent<T> | null;
export interface ContextMenuActionEvent<T> {
selected: (actionIndex: number | null, value: T | null) => void;
}
export default function ContextMenu<T>({ actionItems, row = null, onContextMenuItemClicked} : { actionItems: ContextMenuItem[], row?: T | null, onContextMenuItemClicked?: ContextMenuActionEvent<T>}) {
const muiTheme = useTheme();
const state = useSelector((state: RootState) => state.contextMenu)
const dispatch = useDispatch();
const [visible, setVisible] = useState(false);
const [position, setPosition] = useState({ top: 0, left: 0 });
useEffect(() => {
setVisible(state.visible)
const position = state.position
if (position) {
setPosition({top: position.y, left: position.x})
}
}, [state])
useEffect(() => {
const handleClick = () => dispatch(setContextMenuVisible(false));
window.addEventListener("click", handleClick);
return () => {
window.removeEventListener("click", handleClick);
};
}, [dispatch]);
return (
<>
{visible && (
<Box className="contextmenu" sx={{
top: position.top,
left: position.left,
backgroundColor: muiTheme.palette.action.selected,
}}>
{ actionItems.map((item, index) => (
<Box className="contextMenuItem" display="flex" key={index} onClick={() => {
onContextMenuItemClicked?.selected(item.actionIndex, row)
}} >
{item.icon}
<Typography>{item.text}</Typography>
</Box>
))}
{actionItems.length === 0 && (
<Typography>Nothing to do..</Typography>
)}
</Box>
)}
</>
)
}

View File

@ -0,0 +1,31 @@
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
interface ContextMenuPosition {
x: number,
y: number
}
interface ContextMenuState {
visible: boolean,
position?: ContextMenuPosition
}
const initialState: ContextMenuState = {
visible: false
}
const contextMenuSlice = createSlice({
name: 'ContextMenu',
initialState,
reducers: {
setContextMenuVisible(state, action: PayloadAction<boolean>) {
state.visible = action.payload
},
setContextMenuPosition(state, action: PayloadAction<ContextMenuPosition>) {
state.position = action.payload
}
}
});
export const { setContextMenuVisible, setContextMenuPosition } = contextMenuSlice.actions;
export default contextMenuSlice.reducer;

View File

@ -0,0 +1,33 @@
export function canEncode(extension: string): boolean {
const supported = [
"mkv",
"avi",
"mp4",
"wmv",
"webm",
"mov"
]
const found = supported.find((item) => item === extension)
return (found) ? true : false;
}
export function canExtract(extension: string): boolean {
const supported = [
"mkv"
]
const found = supported.find((item) => item === extension)
return (found) ? true : false;
}
export function canConvert(extension: string): boolean {
const supported = [
"ass",
"srt",
"vtt",
"smi"
]
const found = supported.find((item) => item === extension)
return (found) ? true : false;
}