Render plugin data from static server
This commit is contained in:
parent
74c8920edf
commit
6a76bfac33
@ -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: </strong>
|
||||
{formatBytes(plugin.size)}
|
||||
</div>
|
||||
<div>
|
||||
<strong>Cell edits: </strong>
|
||||
{plugin.cells.length}
|
||||
{plugin.cell_count}
|
||||
</div>
|
||||
{plugin.description && (
|
||||
<div>
|
||||
|
@ -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} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -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") {
|
||||
|
@ -42,4 +42,17 @@ export const parsePluginFiles = (pluginFiles: File[], workerPool: WorkerPool) =>
|
||||
contents,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
@ -38,6 +38,7 @@ export interface PluginFile {
|
||||
hash: string;
|
||||
parseError?: string;
|
||||
enabled: boolean;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export type PluginsState = {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user