2022-06-01 03:55:36 +00:00
|
|
|
import { createPortal } from "react-dom";
|
2022-08-19 22:39:05 +00:00
|
|
|
import React, { useCallback, useEffect, useState, useRef } from "react";
|
2022-08-18 03:19:55 +00:00
|
|
|
import { useDispatch } from "react-redux";
|
|
|
|
import useSWRImmutable from "swr/immutable";
|
2022-06-01 03:55:36 +00:00
|
|
|
|
|
|
|
import AddModData from "./AddModData";
|
|
|
|
import SearchBar from "./SearchBar";
|
2022-08-18 03:19:55 +00:00
|
|
|
import { jsonFetcher } from "../lib/api";
|
|
|
|
import { updateFetchedPlugin, PluginsByHashWithMods } from "../slices/plugins";
|
2022-06-01 03:55:36 +00:00
|
|
|
import styles from "../styles/AddModDialog.module.css";
|
2022-08-19 22:39:05 +00:00
|
|
|
import EscapeListener from "./EscapeListener";
|
2022-06-01 03:55:36 +00:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
counts: Record<number, [number, number, number]> | null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const AddModDialog: React.FC<Props> = ({ counts }) => {
|
|
|
|
const [selectedMod, setSelectedMod] = useState<number | null>(null);
|
2022-08-18 03:19:55 +00:00
|
|
|
const [selectedPlugin, setSelectedPlugin] = useState<string | null>(null);
|
2022-06-01 03:55:36 +00:00
|
|
|
const [dialogShown, setDialogShown] = useState(false);
|
|
|
|
const searchInput = useRef<HTMLInputElement | null>(null);
|
2022-08-18 03:19:55 +00:00
|
|
|
const dispatch = useDispatch();
|
2022-06-01 03:55:36 +00:00
|
|
|
|
2022-08-18 03:19:55 +00:00
|
|
|
const { data, error } = useSWRImmutable(
|
|
|
|
selectedPlugin
|
|
|
|
? `https://plugins.modmapper.com/${selectedPlugin}.json`
|
|
|
|
: null,
|
|
|
|
(_) => jsonFetcher<PluginsByHashWithMods>(_)
|
|
|
|
);
|
|
|
|
|
|
|
|
const onAddModButtonClick = useCallback(async () => {
|
2022-06-01 03:55:36 +00:00
|
|
|
setSelectedMod(null);
|
|
|
|
setDialogShown(true);
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
if (searchInput.current) searchInput.current.focus();
|
|
|
|
});
|
2022-08-18 03:19:55 +00:00
|
|
|
}, [setSelectedMod, setDialogShown]);
|
2022-06-01 03:55:36 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2022-08-19 22:39:05 +00:00
|
|
|
<EscapeListener onEscape={() => setDialogShown(false)} />
|
2022-06-01 03:55:36 +00:00
|
|
|
<button onClick={onAddModButtonClick}>Add mod</button>
|
|
|
|
{typeof window !== "undefined" &&
|
|
|
|
createPortal(
|
|
|
|
<dialog open={dialogShown} className={styles.dialog}>
|
|
|
|
<h3>Add mod</h3>
|
|
|
|
<SearchBar
|
|
|
|
counts={counts}
|
|
|
|
sidebarOpen={false}
|
|
|
|
placeholder="Search mods…"
|
|
|
|
onSelectResult={(selectedItem) => {
|
|
|
|
if (selectedItem) {
|
|
|
|
setSelectedMod(selectedItem.id);
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
inputRef={searchInput}
|
|
|
|
/>
|
|
|
|
{selectedMod && (
|
2022-08-18 03:19:55 +00:00
|
|
|
<AddModData
|
|
|
|
selectedMod={selectedMod}
|
|
|
|
selectedPlugin={selectedPlugin}
|
|
|
|
setSelectedPlugin={setSelectedPlugin}
|
|
|
|
counts={counts}
|
|
|
|
/>
|
2022-06-01 03:55:36 +00:00
|
|
|
)}
|
|
|
|
<menu>
|
|
|
|
<button
|
|
|
|
onClick={() => {
|
|
|
|
setSelectedMod(null);
|
|
|
|
setDialogShown(false);
|
|
|
|
if (searchInput.current) searchInput.current.value = "";
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
Cancel
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
onClick={() => {
|
2022-08-19 22:39:05 +00:00
|
|
|
if (data)
|
|
|
|
dispatch(updateFetchedPlugin({ ...data, enabled: true }));
|
2022-06-01 03:55:36 +00:00
|
|
|
setDialogShown(false);
|
|
|
|
}}
|
2022-08-18 03:19:55 +00:00
|
|
|
disabled={!selectedMod || !selectedPlugin || !data}
|
2022-06-01 03:55:36 +00:00
|
|
|
>
|
|
|
|
Add
|
|
|
|
</button>
|
|
|
|
</menu>
|
|
|
|
</dialog>,
|
|
|
|
document.body
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default AddModDialog;
|