Migrate react-contextmenu to react-contexify

This commit is contained in:
Marks Polakovs 2020-11-09 14:30:50 +00:00
parent 1e5aae0b51
commit feccb3155e
6 changed files with 82 additions and 48 deletions

View file

@ -76,7 +76,7 @@
"react-app-polyfill": "^1.0.4",
"react-beautiful-dnd": "^12.1.1",
"react-beforeunload": "^2.1.0",
"react-contextmenu": "^2.13.0",
"react-contexify": "^4.1.1",
"react-dev-utils": "^9.1.0",
"react-dnd": "^9.4.0",
"react-dnd-html5-backend": "^9.4.0",

View file

@ -77,7 +77,7 @@ interface Album {
// TODO
}
interface TimeslotItemBase {
export interface TimeslotItemBase {
timeslotitemid: string;
channel: number;
weight: number;
@ -88,7 +88,7 @@ interface TimeslotItemBase {
cue: number;
}
interface TimeslotItemCentral {
export interface TimeslotItemCentral {
type: "central";
artist: string;
intro: number;

View file

@ -1,15 +1,16 @@
import React, { memo } from "react";
import { PlanItem, itemId } from "./state";
import { PlanItem, itemId, isTrack, isAux } from "./state";
import { Track, AuxItem } from "../api";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../rootReducer";
import * as MixerState from "../mixer/state";
import { Draggable } from "react-beautiful-dnd";
import { ContextMenuTrigger } from "react-contextmenu";
import { contextMenu } from "react-contexify";
import "./item.scss";
export const TS_ITEM_MENU_ID = "SongMenu";
export const TS_ITEM_AUX_ID = "AuxMenu";
export const Item = memo(function Item({
item: x,
@ -22,7 +23,6 @@ export const Item = memo(function Item({
}) {
const dispatch = useDispatch();
const id = itemId(x);
const isReal = "timeslotitemid" in x;
const isGhost = "ghostid" in x;
const playerState = useSelector((state: RootState) =>
@ -44,6 +44,30 @@ export const Item = memo(function Item({
}
}
function openContextMenu(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
e.preventDefault();
if (isTrack(x)) {
contextMenu.show({
id: TS_ITEM_MENU_ID,
event: e,
props: {
id,
title: x.title,
artist: x.artist,
},
});
} else if (isAux(x)) {
contextMenu.show({
id: TS_ITEM_MENU_ID,
event: e,
props: {
id,
title: x.title,
},
});
}
}
return (
<Draggable
draggableId={id}
@ -69,31 +93,27 @@ export const Item = memo(function Item({
}`
}
onClick={triggerClick}
onContextMenu={openContextMenu}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<ContextMenuTrigger
id={isReal ? TS_ITEM_MENU_ID : ""}
collect={() => ({ id })}
<span className={"icon " + x.type} />
&nbsp;
{x.title.toString()}
{"artist" in x && x.artist !== "" && " - " + x.artist}
<small
className={
"border rounded border-danger text-danger p-1 m-1" +
("clean" in x && x.clean === false ? "" : " d-none")
}
>
<span className={"icon " + x.type} />
&nbsp;
{x.title.toString()}
{"artist" in x && x.artist !== "" && " - " + x.artist}
<small
className={
"border rounded border-danger text-danger p-1 m-1" +
("clean" in x && x.clean === false ? "" : " d-none")
}
>
Explicit
</small>
{showDebug && (
<code>
{itemId(x)} {"channel" in x && x.channel + "/" + x.weight}
</code>
)}
</ContextMenuTrigger>
Explicit
</small>
{showDebug && (
<code>
{itemId(x)} {"channel" in x && x.channel + "/" + x.weight}
</code>
)}
</div>
)}
</Draggable>

View file

@ -1,5 +1,6 @@
import React, { useState, useReducer, useEffect } from "react";
import { ContextMenu, MenuItem } from "react-contextmenu";
import { Menu, Item as CtxMenuItem } from "react-contexify";
import "react-contexify/dist/ReactContexify.min.css";
import { useBeforeunload } from "react-beforeunload";
import {
FaBookOpen,
@ -379,13 +380,6 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
}
}
async function onCtxRemoveClick(e: any, data: { id: string }) {
dispatch(removeItem(timeslotId, data.id));
}
async function onCtxUnPlayedClick(e: any, data: { id: string }) {
dispatch(setItemPlayed({ itemId: data.id, played: false }));
}
// Add support for reloading the show plan from the iFrames.
// There is a similar listener in showplanner/ImporterModal.tsx to handle closing the iframe.
useEffect(() => {
@ -440,14 +434,24 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
</div>
</DragDropContext>
</div>
<ContextMenu id={TS_ITEM_MENU_ID}>
<MenuItem onClick={onCtxRemoveClick}>
<Menu id={TS_ITEM_MENU_ID}>
<CtxMenuItem
onClick={(args) =>
dispatch(removeItem(timeslotId, (args.props as any).id))
}
>
<FaTrash /> Remove
</MenuItem>
<MenuItem onClick={onCtxUnPlayedClick}>
</CtxMenuItem>
<CtxMenuItem
onClick={(args) =>
dispatch(
setItemPlayed({ itemId: (args.props as any).id, played: false })
)
}
>
<FaCircleNotch /> Mark Unplayed
</MenuItem>
</ContextMenu>
</CtxMenuItem>
</Menu>
<OptionsMenu />
<WelcomeModal
isOpen={showWelcomeModal}

View file

@ -47,6 +47,16 @@ export function itemId(
throw new Error("Can't get id of unknown item.");
}
export function isTrack(
item: PlanItem | Track | AuxItem
): item is (api.TimeslotItemBase & api.TimeslotItemCentral) | Track {
return "trackid" in item;
}
export function isAux(item: PlanItem | Track | AuxItem): item is AuxItem {
return "auxid" in item;
}
interface ShowplanState {
planLoading: boolean;
planLoadError: string | null;

View file

@ -3299,7 +3299,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.3, classnames@^2.2.5:
classnames@^2.2.3, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
@ -10100,13 +10100,13 @@ react-beforeunload@^2.1.0:
dependencies:
prop-types "^15.7.2"
react-contextmenu@^2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/react-contextmenu/-/react-contextmenu-2.13.0.tgz#dabaea63124e30c85f1b4245c095b7045d013459"
integrity sha512-hhFuJX4di0zGV7H7pXPn42U70OZbGpQD+PxcdmKStNT5mebSjI+inhOuFESDmDbqVsN/f99hI5/nw95oXTVRXQ==
react-contexify@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-contexify/-/react-contexify-4.1.1.tgz#f5eba1ad82a923c033c91d0abcea1da0a71ebaa1"
integrity sha512-WJeRI4ohHEOmNiH0xb62a/eV+5ae168FB7H6pfbeEVJkf0UN7D5H99l6b89poc2LHKN1gOimFjREyY8quGVsXA==
dependencies:
classnames "^2.2.5"
object-assign "^4.1.0"
classnames "^2.2.6"
prop-types "^15.6.2"
react-dev-utils@^10.2.1:
version "10.2.1"