Render plugin data from static server

This commit is contained in:
Tyler Hallada 2022-03-12 14:00:40 -05:00
parent 74c8920edf
commit 6a76bfac33
6 changed files with 57 additions and 41 deletions

View File

@ -2,24 +2,16 @@ import Head from "next/head";
import React from "react";
import styles from "../styles/PluginData.module.css";
import { Cell } from "./CellData";
import { formatBytes } from "../lib/plugins";
export interface Plugin {
id: number;
name: string;
hash: bigint;
file_id: number;
mod_id: number;
version: number;
hash: string;
size: number;
author?: string;
description?: string;
masters: string[];
file_name: string;
file_path: string;
updated_at: Date;
created_at: Date;
cells: Omit<Cell, "mods">[];
cell_count: number;
}
type Props = {
@ -39,7 +31,7 @@ const PluginData: React.FC<Props> = ({ plugin, counts }) => {
<meta
key="description"
name="description"
content={`Map of Skyrim showing ${plugin.cells.length} cell edits from the plugin: ${plugin.file_name}`}
content={`Map of Skyrim showing ${plugin.cell_count} cell edits from the plugin: ${plugin.file_name}`}
/>
<meta
key="og:title"
@ -49,7 +41,7 @@ const PluginData: React.FC<Props> = ({ plugin, counts }) => {
<meta
key="og:description"
property="og:description"
content={`Map of Skyrim showing ${plugin.cells.length} cell edits from the plugin: ${plugin.file_name}`}
content={`Map of Skyrim showing ${plugin.cell_count} cell edits from the plugin: ${plugin.file_name}`}
/>
<meta
key="twitter:title"
@ -59,7 +51,7 @@ const PluginData: React.FC<Props> = ({ plugin, counts }) => {
<meta
key="twitter:description"
name="twitter:description"
content={`Map of Skyrim showing ${plugin.cells.length} cell edits from the plugin: ${plugin.file_name}`}
content={`Map of Skyrim showing ${plugin.cell_count} cell edits from the plugin: ${plugin.file_name}`}
/>
<meta
key="og:url"
@ -80,9 +72,13 @@ const PluginData: React.FC<Props> = ({ plugin, counts }) => {
{plugin.masters.join(", ")}
</div>
)}
<div>
<strong>Size:&nbsp;</strong>
{formatBytes(plugin.size)}
</div>
<div>
<strong>Cell edits:&nbsp;</strong>
{plugin.cells.length}
{plugin.cell_count}
</div>
{plugin.description && (
<div>

View File

@ -2,8 +2,11 @@ import React from "react";
import useSWRImmutable from "swr/immutable";
import { useAppSelector } from "../lib/hooks";
import { PluginFile } from "../slices/plugins";
import { Mod } from "./ModData";
import PluginData from "./PluginData";
import { Cell } from "./CellData";
import CellModList from "./CellModList";
import PluginData, { Plugin as PluginProps } from "./PluginData";
import styles from "../styles/PluginData.module.css";
export interface File {
@ -40,13 +43,19 @@ export interface Plugin {
file_path: string;
updated_at: Date;
created_at: Date;
file: File;
mod: Omit<Mod, "cells">;
}
export interface PluginsByHashWithMods {
hash: number;
plugins: Plugin[];
files: File[];
mods: Mod[];
cells: Cell[];
}
const NEXUS_MODS_URL = "https://www.nexusmods.com/skyrimspecialedition";
const jsonFetcher = async (url: string): Promise<Plugin | null> => {
const jsonFetcher = async (url: string): Promise<PluginsByHashWithMods | null> => {
const res = await fetch(url);
if (!res.ok) {
@ -59,6 +68,20 @@ const jsonFetcher = async (url: string): Promise<Plugin | null> => {
return res.json();
};
const buildPluginProps = (data?: PluginsByHashWithMods | null, plugin?: PluginFile): PluginProps => {
const dataPlugin = data && data.plugins.length > 0 && data.plugins[0];
return {
hash: (plugin && plugin.hash) || (dataPlugin && dataPlugin.hash.toString(36)) || "",
size: plugin?.size || (dataPlugin && dataPlugin.size) || 0,
author: plugin?.parsed?.header.author || (dataPlugin && dataPlugin.author) || undefined,
description: plugin?.parsed?.header.description || (dataPlugin && dataPlugin.description) || undefined,
masters: plugin?.parsed?.header.masters || (dataPlugin && dataPlugin.masters) || [],
file_name: plugin?.filename || (dataPlugin && dataPlugin.file_name) || "",
cell_count: plugin?.parsed?.cells.length || (data && data.cells.length) || 0,
}
}
type Props = {
hash: string;
counts: Record<number, [number, number, number]> | null;
@ -86,27 +109,10 @@ const PluginDetail: React.FC<Props> = ({ hash, counts }) => {
return (
<>
<PluginData
plugin={
// TODO: merge into one common plugin object
data || {
id: plugin!.id,
name: plugin!.name,
hash: plugin!.hash,
file_id: plugin!.file_id,
mod_id: plugin!.mod_id,
version: plugin!.version,
size: plugin!.size,
author: plugin!.author,
description: plugin!.description,
masters: plugin!.masters,
file_name: plugin!.filename,
file_path: plugin!.filepath,
updated_at: plugin!.updated_at,
created_at: plugin!.created_at,
cells: plugin!.cells,
}
}
plugin={buildPluginProps(data, plugin)}
counts={counts}
/>
{data && <CellModList mods={data.mods} counts={counts} />}
</>
);
};

View File

@ -42,7 +42,7 @@ export class WorkerPool {
return new Promise((resolve) => {
const worker = new Worker();
worker.onmessage = (evt: {
data: string | PluginFile & { timeHashEnd: number };
data: string | PluginFile;
}) => {
const { data } = evt;
if (typeof data === "string" && data === "ready") {

View File

@ -43,3 +43,16 @@ export const parsePluginFiles = (pluginFiles: File[], workerPool: WorkerPool) =>
});
});
}
// From: https://stackoverflow.com/a/18650828
export const formatBytes = (bytes: number, decimals = 2): string => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

View File

@ -38,6 +38,7 @@ export interface PluginFile {
hash: string;
parseError?: string;
enabled: boolean;
size: number;
}
export type PluginsState = {

View File

@ -19,7 +19,7 @@ self.addEventListener("message", async (event: MessageEvent<{ skipParsing?: bool
}
}
const hash = hash_plugin(contents).toString(36);
self.postMessage({ filename, lastModified, parsed, hash, parseError, enabled: parsed && !parseError, timeHashEnd: Date.now() });
self.postMessage({ filename, lastModified, parsed, hash, parseError, enabled: parsed && !parseError, size: contents.length });
} catch (error) {
console.error(error);
self.postMessage(error);