Basic plugin data page
This commit is contained in:
parent
761ef80669
commit
f6d02c6d33
@ -143,6 +143,7 @@ const Map: React.FC = () => {
|
|||||||
|
|
||||||
const selectCells = useCallback(
|
const selectCells = useCallback(
|
||||||
(cells: { x: number; y: number }[]) => {
|
(cells: { x: number; y: number }[]) => {
|
||||||
|
console.log("selectCells");
|
||||||
if (!map.current) return;
|
if (!map.current) return;
|
||||||
if (map.current && !map.current.getSource("grid-source")) return;
|
if (map.current && !map.current.getSource("grid-source")) return;
|
||||||
|
|
||||||
@ -233,6 +234,7 @@ const Map: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const clearSelectedCell = useCallback(() => {
|
const clearSelectedCell = useCallback(() => {
|
||||||
|
console.log("clearSelectedCell");
|
||||||
setSelectedCell(null);
|
setSelectedCell(null);
|
||||||
if (map.current) map.current.removeFeatureState({ source: "grid-source" });
|
if (map.current) map.current.removeFeatureState({ source: "grid-source" });
|
||||||
if (map.current) {
|
if (map.current) {
|
||||||
@ -245,6 +247,7 @@ const Map: React.FC = () => {
|
|||||||
}, [map]);
|
}, [map]);
|
||||||
|
|
||||||
const clearSelectedCells = useCallback(() => {
|
const clearSelectedCells = useCallback(() => {
|
||||||
|
console.log("clearSelectedCells");
|
||||||
setSelectedCells(null);
|
setSelectedCells(null);
|
||||||
if (map.current) {
|
if (map.current) {
|
||||||
map.current.removeFeatureState({ source: "selected-cell-source" });
|
map.current.removeFeatureState({ source: "selected-cell-source" });
|
||||||
@ -295,24 +298,45 @@ const Map: React.FC = () => {
|
|||||||
clearSelectedCell();
|
clearSelectedCell();
|
||||||
setSidebarOpen(true);
|
setSidebarOpen(true);
|
||||||
selectCells(selectedCells);
|
selectCells(selectedCells);
|
||||||
} else {
|
} else if (router.query.plugin && typeof router.query.plugin === "string") {
|
||||||
if (selectedCell) {
|
|
||||||
clearSelectedCell();
|
|
||||||
}
|
|
||||||
if (selectedCells) {
|
|
||||||
clearSelectedCells();
|
clearSelectedCells();
|
||||||
|
setSidebarOpen(true);
|
||||||
|
if (plugins && plugins.length > 0 && pluginsPending === 0) {
|
||||||
|
const plugin = plugins.find((p) => p.hash === router.query.plugin);
|
||||||
|
if (plugin && plugin.parsed) {
|
||||||
|
const cells = [];
|
||||||
|
const cellSet = new Set<number>();
|
||||||
|
for (const cell of plugin.parsed.cells) {
|
||||||
|
if (
|
||||||
|
cell.x !== undefined &&
|
||||||
|
cell.y !== undefined &&
|
||||||
|
cell.world_form_id === 60 &&
|
||||||
|
cellSet.has(cell.x + cell.y * 1000) === false
|
||||||
|
) {
|
||||||
|
cells.push({ x: cell.x, y: cell.y });
|
||||||
|
cellSet.add(cell.x + cell.y * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
selectCells(cells);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearSelectedCell();
|
||||||
|
clearSelectedCells();
|
||||||
|
}
|
||||||
}, [
|
}, [
|
||||||
selectedCell,
|
selectedCell,
|
||||||
selectedCells,
|
selectedCells,
|
||||||
router.query.cell,
|
router.query.cell,
|
||||||
router.query.mod,
|
router.query.mod,
|
||||||
|
router.query.plugin,
|
||||||
selectCell,
|
selectCell,
|
||||||
selectCells,
|
selectCells,
|
||||||
clearSelectedCell,
|
clearSelectedCell,
|
||||||
clearSelectedCells,
|
clearSelectedCells,
|
||||||
heatmapLoaded,
|
heatmapLoaded,
|
||||||
|
plugins,
|
||||||
|
pluginsPending,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -324,7 +348,14 @@ const Map: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!heatmapLoaded) return; // wait for all map layers to load
|
if (!heatmapLoaded) return; // wait for all map layers to load
|
||||||
if (plugins && plugins.length > 0 && pluginsPending === 0) {
|
if (
|
||||||
|
plugins &&
|
||||||
|
plugins.length > 0 &&
|
||||||
|
pluginsPending === 0 &&
|
||||||
|
!router.query.cell &&
|
||||||
|
!router.query.mod &&
|
||||||
|
!router.query.plugin
|
||||||
|
) {
|
||||||
clearSelectedCells();
|
clearSelectedCells();
|
||||||
const cells = plugins.reduce(
|
const cells = plugins.reduce(
|
||||||
(acc: { x: number; y: number }[], plugin: PluginFile) => {
|
(acc: { x: number; y: number }[], plugin: PluginFile) => {
|
||||||
@ -347,7 +378,16 @@ const Map: React.FC = () => {
|
|||||||
);
|
);
|
||||||
selectCells(cells);
|
selectCells(cells);
|
||||||
}
|
}
|
||||||
}, [plugins, pluginsPending, heatmapLoaded, clearSelectedCells, selectCells]);
|
}, [
|
||||||
|
plugins,
|
||||||
|
pluginsPending,
|
||||||
|
heatmapLoaded,
|
||||||
|
clearSelectedCells,
|
||||||
|
selectCells,
|
||||||
|
router.query.cell,
|
||||||
|
router.query.mod,
|
||||||
|
router.query.plugin,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (map.current) return; // initialize map only once
|
if (map.current) return; // initialize map only once
|
||||||
|
115
components/PluginData.tsx
Normal file
115
components/PluginData.tsx
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import Head from "next/head";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useAppSelector } from "../lib/hooks";
|
||||||
|
import styles from "../styles/PluginData.module.css";
|
||||||
|
|
||||||
|
export interface CellCoord {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NEXUS_MODS_URL = "https://www.nexusmods.com/skyrimspecialedition";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
hash: string;
|
||||||
|
counts: Record<number, [number, number, number]> | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PluginData: React.FC<Props> = ({ hash, counts }) => {
|
||||||
|
const plugins = useAppSelector((state) => state.plugins.plugins);
|
||||||
|
const plugin = plugins.find((plugin) => plugin.hash === hash);
|
||||||
|
|
||||||
|
if (!plugin) {
|
||||||
|
return <h3>Plugin could not be found</h3>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title key="title">{`Modmapper - ${plugin.filename}`}</title>
|
||||||
|
<meta
|
||||||
|
key="description"
|
||||||
|
name="description"
|
||||||
|
content={`Map of Skyrim showing ${
|
||||||
|
plugin.parsed ? plugin.parsed.cells.length : 0
|
||||||
|
} cell edits from the plugin: ${plugin.filename}`}
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
key="og:title"
|
||||||
|
property="og:title"
|
||||||
|
content={`Modmapper - ${plugin.filename}`}
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
key="og:description"
|
||||||
|
property="og:description"
|
||||||
|
content={`Map of Skyrim showing ${
|
||||||
|
plugin.parsed ? plugin.parsed.cells.length : 0
|
||||||
|
} cell edits from the plugin: ${plugin.filename}`}
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
key="twitter:title"
|
||||||
|
name="twitter:title"
|
||||||
|
content={`Modmapper - ${plugin.filename}`}
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
key="twitter:description"
|
||||||
|
name="twitter:description"
|
||||||
|
content={`Map of Skyrim showing ${
|
||||||
|
plugin.parsed ? plugin.parsed.cells.length : 0
|
||||||
|
} cell edits from the plugin: ${plugin.filename}`}
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
key="og:url"
|
||||||
|
property="og:url"
|
||||||
|
content={`https://modmapper.com/?plugin=${plugin.hash}`}
|
||||||
|
/>
|
||||||
|
</Head>
|
||||||
|
<h1 className={styles.name}>{plugin.filename}</h1>
|
||||||
|
{plugin.parsed && (
|
||||||
|
<div>
|
||||||
|
<strong>Version: </strong>
|
||||||
|
{plugin.parsed.header.version}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parsed && plugin.parsed.header.author && (
|
||||||
|
<div>
|
||||||
|
<strong>Author: </strong>
|
||||||
|
{plugin.parsed.header.author}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parsed && plugin.parsed.header.masters && (
|
||||||
|
<div>
|
||||||
|
<strong>Master plugins: </strong>
|
||||||
|
{plugin.parsed.header.masters.join(", ")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parsed && (
|
||||||
|
<div>
|
||||||
|
<strong>Cell edits: </strong>
|
||||||
|
{plugin.parsed.cells.length}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parsed && (
|
||||||
|
<div>
|
||||||
|
<strong>World edits: </strong>
|
||||||
|
{plugin.parsed.worlds.length}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parsed && plugin.parsed.header.description && (
|
||||||
|
<div>
|
||||||
|
<h3>Description:</h3>
|
||||||
|
<p>{plugin.parsed.header.description}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{plugin.parseError && (
|
||||||
|
<div>
|
||||||
|
<h3>Failed to parse plugin:</h3>
|
||||||
|
<p>{plugin.parseError}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PluginData;
|
@ -4,6 +4,7 @@ import { formatRelative } from "date-fns";
|
|||||||
|
|
||||||
import CellData from "./CellData";
|
import CellData from "./CellData";
|
||||||
import ModData from "./ModData";
|
import ModData from "./ModData";
|
||||||
|
import PluginData from "./PluginData";
|
||||||
import PluginsLoader from "./PluginsLoader";
|
import PluginsLoader from "./PluginsLoader";
|
||||||
import styles from "../styles/Sidebar.module.css";
|
import styles from "../styles/Sidebar.module.css";
|
||||||
|
|
||||||
@ -56,6 +57,13 @@ const Sidebar: React.FC<Props> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderPluginData = (plugin: string) => {
|
||||||
|
if (countsError) return renderLoadError(countsError);
|
||||||
|
if (!counts) return renderLoading();
|
||||||
|
|
||||||
|
return <PluginData hash={plugin} counts={counts} />;
|
||||||
|
};
|
||||||
|
|
||||||
const renderOpenSidebar = () => {
|
const renderOpenSidebar = () => {
|
||||||
if (selectedCell) {
|
if (selectedCell) {
|
||||||
return (
|
return (
|
||||||
@ -89,6 +97,24 @@ const Sidebar: React.FC<Props> = ({
|
|||||||
{!Number.isNaN(modId) && renderModData(modId)}
|
{!Number.isNaN(modId) && renderModData(modId)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (router.query.plugin) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles.sidebar}
|
||||||
|
style={!open ? { display: "none" } : {}}
|
||||||
|
>
|
||||||
|
<div className={styles["sidebar-header"]}>
|
||||||
|
<button className={styles.close} onClick={onClose}>
|
||||||
|
✖
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{renderPluginData(
|
||||||
|
typeof router.query.plugin === "string"
|
||||||
|
? router.query.plugin
|
||||||
|
: router.query.plugin[0]
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
4
styles/PluginData.module.css
Normal file
4
styles/PluginData.module.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
h1.name {
|
||||||
|
line-height: 1.75rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user