diff --git a/components/DataDirPicker.tsx b/components/DataDirPicker.tsx new file mode 100644 index 0000000..72e8757 --- /dev/null +++ b/components/DataDirPicker.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useRef } from "react"; + +import { useAppSelector, useAppDispatch } from "../lib/hooks"; +import { + addPluginInOrder, + clearPlugins, + setPending, + decrementPending, + PluginFile, +} from "../slices/plugins"; +import styles from "../styles/DataDirPicker.module.css"; + +export const excludedPlugins = [ + "Skyrim.esm", + "Update.esm", + "Dawnguard.esm", + "HearthFires.esm", + "Dragonborn.esm", +]; + +type Props = {}; + +const DataDirPicker: React.FC = () => { + const workerRef = useRef(); + const dispatch = useAppDispatch(); + const plugins = useAppSelector((state) => state.plugins.plugins); + + useEffect(() => { + async function loadWorker() { + const { default: Worker } = await import( + "worker-loader?filename=static/[fullhash].worker.js!../workers/PluginsLoader.worker" + ); + console.log(Worker); + workerRef.current = new Worker(); + workerRef.current.onmessage = (evt: { data: PluginFile }) => { + const { data } = evt; + console.log(`WebWorker Response =>`); + dispatch(decrementPending(1)); + console.log(data.parsed); + dispatch(addPluginInOrder(data)); + }; + } + loadWorker(); + return () => { + if (workerRef.current) { + workerRef.current.terminate(); + } + }; + }, [dispatch]); + + const onDataDirButtonClick = async () => { + if (!workerRef.current) { + return alert("Worker not loaded yet"); + } + const dirHandle = await ( + window as Window & typeof globalThis & { showDirectoryPicker: () => any } + ).showDirectoryPicker(); + dispatch(clearPlugins()); + const values = dirHandle.values(); + const plugins = []; + while (true) { + const next = await values.next(); + if (next.done) { + break; + } + if ( + next.value.kind == "file" && + (next.value.name.endsWith(".esp") || + next.value.name.endsWith(".esm") || + next.value.name.endsWith(".esl")) + ) { + console.log(next.value); + plugins.push(next.value); + } + } + dispatch(setPending(plugins.length)); + + for (const plugin of plugins) { + const file = await plugin.getFile(); + console.log(file.lastModified); + console.log(file.lastModifiedDate); + const contents = new Uint8Array(await file.arrayBuffer()); + try { + workerRef.current.postMessage( + { + skipParsing: excludedPlugins.includes(plugin.name), + filename: plugin.name, + lastModified: file.lastModified, + contents, + }, + [contents.buffer] + ); + } catch (error) { + console.error(error); + } + } + }; + + return ( + <> +

+ To see all of the cell edits and conflicts for your current mod load + order select your Data directory below to load the plugins. +

+ + + ); +}; + +export default DataDirPicker; diff --git a/components/PluginTxtEditor.tsx b/components/PluginTxtEditor.tsx new file mode 100644 index 0000000..f2fe519 --- /dev/null +++ b/components/PluginTxtEditor.tsx @@ -0,0 +1,88 @@ +import { createPortal } from "react-dom"; +import React, { useEffect, useState } from "react"; + +import { useAppSelector, useAppDispatch } from "../lib/hooks"; +import { setPluginsTxt } from "../slices/pluginsTxt"; +import { applyLoadOrder } from "../slices/plugins"; +import styles from "../styles/PluginTxtEditor.module.css"; + +export const excludedPlugins = [ + "Skyrim.esm", + "Update.esm", + "Dawnguard.esm", + "HearthFires.esm", + "Dragonborn.esm", +]; + +type Props = {}; + +const PluginsLoader: React.FC = () => { + const [editPluginsTxt, setEditPluginsTxt] = useState(null); + const [pluginsTxtShown, setPluginsTxtShown] = useState(false); + const dispatch = useAppDispatch(); + const pluginsTxt = useAppSelector((state) => state.pluginsTxt); + + useEffect(() => { + setPluginsTxtShown(false); + console.log("going to apply!"); + dispatch(applyLoadOrder()); + }, [dispatch, pluginsTxt]); + + const onPluginsTxtButtonClick = async () => { + setEditPluginsTxt(pluginsTxt); + setPluginsTxtShown(true); + }; + + return ( + <> +

+ Paste or drag-and-drop your plugins.txt below to sort and + enable the loaded plugins by your current load order. +

+ + {process.browser && + createPortal( + +

Paste plugins.txt

+

+ The plugins.txt file is typically found at{" "} + + C:\Users\username\AppData\Local\Skyrim Special Edition + + . You can also drag-and-drop the file anywhere on the window to + load the file. +

+