EscapeListener and display added plugins on map

This commit is contained in:
Tyler Hallada 2022-08-19 18:39:05 -04:00
parent 2065b5fa3a
commit 9f86fe1571
4 changed files with 55 additions and 10 deletions

View File

@ -1,5 +1,5 @@
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
import React, { useCallback, useState, useRef } from "react"; import React, { useCallback, useEffect, useState, useRef } from "react";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import useSWRImmutable from "swr/immutable"; import useSWRImmutable from "swr/immutable";
@ -8,6 +8,7 @@ import SearchBar from "./SearchBar";
import { jsonFetcher } from "../lib/api"; import { jsonFetcher } from "../lib/api";
import { updateFetchedPlugin, PluginsByHashWithMods } from "../slices/plugins"; import { updateFetchedPlugin, PluginsByHashWithMods } from "../slices/plugins";
import styles from "../styles/AddModDialog.module.css"; import styles from "../styles/AddModDialog.module.css";
import EscapeListener from "./EscapeListener";
type Props = { type Props = {
counts: Record<number, [number, number, number]> | null; counts: Record<number, [number, number, number]> | null;
@ -37,6 +38,7 @@ const AddModDialog: React.FC<Props> = ({ counts }) => {
return ( return (
<> <>
<EscapeListener onEscape={() => setDialogShown(false)} />
<button onClick={onAddModButtonClick}>Add mod</button> <button onClick={onAddModButtonClick}>Add mod</button>
{typeof window !== "undefined" && {typeof window !== "undefined" &&
createPortal( createPortal(
@ -74,7 +76,8 @@ const AddModDialog: React.FC<Props> = ({ counts }) => {
<button <button
onClick={() => { onClick={() => {
console.log(`Adding mod ${selectedMod} ${selectedPlugin}`); console.log(`Adding mod ${selectedMod} ${selectedPlugin}`);
if (data) dispatch(updateFetchedPlugin(data)); if (data)
dispatch(updateFetchedPlugin({ ...data, enabled: true }));
setDialogShown(false); setDialogShown(false);
}} }}
disabled={!selectedMod || !selectedPlugin || !data} disabled={!selectedMod || !selectedPlugin || !data}

View File

@ -0,0 +1,30 @@
import React, { useCallback, useEffect } from "react";
type Props = {
onEscape: () => void;
};
const EscapeListener: React.FC<Props> = ({ onEscape }) => {
const keyHandler = useCallback(
(event) => {
switch (event.keyCode) {
case 27: // escape key
onEscape();
break;
default:
break;
}
},
[onEscape]
);
useEffect(() => {
window.addEventListener("keydown", keyHandler);
return () => window.removeEventListener("keydown", keyHandler);
}, [keyHandler]);
return null;
};
export default EscapeListener;

View File

@ -55,7 +55,10 @@ const Map: React.FC = () => {
const [sidebarOpen, setSidebarOpen] = useState(true); const [sidebarOpen, setSidebarOpen] = useState(true);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const plugins = useAppSelector((state) => state.plugins.parsedPlugins); const parsedPlugins = useAppSelector((state) => state.plugins.parsedPlugins);
const fetchedPlugins = useAppSelector(
(state) => state.plugins.fetchedPlugins
);
const pluginsPending = useAppSelector((state) => state.plugins.pending); const pluginsPending = useAppSelector((state) => state.plugins.pending);
const selectedFetchedPlugin = useAppSelector( const selectedFetchedPlugin = useAppSelector(
(state) => state.plugins.selectedFetchedPlugin (state) => state.plugins.selectedFetchedPlugin
@ -299,8 +302,10 @@ const Map: React.FC = () => {
} else if (router.query.plugin && typeof router.query.plugin === "string") { } else if (router.query.plugin && typeof router.query.plugin === "string") {
clearSelectedCell(); clearSelectedCell();
setSidebarOpen(true); setSidebarOpen(true);
if (plugins && plugins.length > 0 && pluginsPending === 0) { if (parsedPlugins && parsedPlugins.length > 0 && pluginsPending === 0) {
const plugin = plugins.find((p) => p.hash === router.query.plugin); const plugin = parsedPlugins.find(
(p) => p.hash === router.query.plugin
);
if (plugin && plugin.parsed) { if (plugin && plugin.parsed) {
const cells = []; const cells = [];
const cellSet = new Set<number>(); const cellSet = new Set<number>();
@ -325,13 +330,12 @@ const Map: React.FC = () => {
} }
if ( if (
plugins && ((parsedPlugins && parsedPlugins.length > 0 && pluginsPending === 0) ||
plugins.length > 0 && fetchedPlugins.length > 0) &&
pluginsPending === 0 &&
!router.query.mod && !router.query.mod &&
!router.query.plugin !router.query.plugin
) { ) {
const cells = plugins.reduce( let cells = parsedPlugins.reduce(
(acc: { x: number; y: number }[], plugin: PluginFile) => { (acc: { x: number; y: number }[], plugin: PluginFile) => {
if (plugin.enabled && plugin.parsed) { if (plugin.enabled && plugin.parsed) {
const newCells = [...acc]; const newCells = [...acc];
@ -351,6 +355,11 @@ const Map: React.FC = () => {
}, },
[] []
); );
cells = cells.concat(
fetchedPlugins
.filter((plugin) => plugin.enabled)
.flatMap((plugin) => plugin.cells)
);
selectCells(cells); selectCells(cells);
} }
}, [ }, [
@ -364,8 +373,9 @@ const Map: React.FC = () => {
clearSelectedCell, clearSelectedCell,
clearSelectedCells, clearSelectedCells,
heatmapLoaded, heatmapLoaded,
plugins, parsedPlugins,
pluginsPending, pluginsPending,
fetchedPlugins,
]); ]);
useEffect(() => { useEffect(() => {

View File

@ -4,6 +4,7 @@ import React, { useEffect, useState } from "react";
import { useAppSelector, useAppDispatch } from "../lib/hooks"; import { useAppSelector, useAppDispatch } from "../lib/hooks";
import { setPluginsTxtAndApplyLoadOrder } from "../slices/pluginsTxt"; import { setPluginsTxtAndApplyLoadOrder } from "../slices/pluginsTxt";
import styles from "../styles/PluginTxtEditor.module.css"; import styles from "../styles/PluginTxtEditor.module.css";
import EscapeListener from "./EscapeListener";
export const excludedPlugins = [ export const excludedPlugins = [
"Skyrim.esm", "Skyrim.esm",
@ -32,6 +33,7 @@ const PluginTxtEditor: React.FC<Props> = () => {
return ( return (
<> <>
<EscapeListener onEscape={() => setPluginsTxtShown(false)} />
<p className={styles["top-spacing"]}> <p className={styles["top-spacing"]}>
<strong className={styles.step}>2. </strong>Paste or drag-and-drop your{" "} <strong className={styles.step}>2. </strong>Paste or drag-and-drop your{" "}
<strong> <strong>