EscapeListener and display added plugins on map
This commit is contained in:
parent
2065b5fa3a
commit
9f86fe1571
@ -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}
|
||||||
|
30
components/EscapeListener.tsx
Normal file
30
components/EscapeListener.tsx
Normal 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;
|
@ -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(() => {
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user