diff --git a/frontend/src/components/Scratch/LibraryPanel.module.css b/frontend/src/components/Scratch/LibraryPanel.module.css deleted file mode 100644 index 919397ed..00000000 --- a/frontend/src/components/Scratch/LibraryPanel.module.css +++ /dev/null @@ -1,86 +0,0 @@ -.section { - padding: 1.5em; - border-radius: 0; - background: transparent; -} - -.section > h3 { - font-size: 1.1em; - font-weight: 500; - - padding: 0.5em; - padding-top: 0; - - color: var(--g1200); -} - -.section:not(:last-child) { - border-bottom: 1px solid var(--a100); -} - -.library { - display: inline-flex; - flex-direction: row; - - width: 100%; - border-radius: 0.5em; -} - -.libraryName { - cursor: default; - font-size: 0.8rem; - - font-size: 1.0em; - font-weight: 500; - - padding: .5em; - -} - -.librarySelect { - flex-grow: 1; -} - -.deleteButton { - display: flex; - align-items: center; - gap: 4px; - padding: 4px 8px; - - cursor: pointer; - - color: var(--g1900); - background: none; - border: 0; - -} -.deleteButton > svg { - width: 1em; - color: var(--g1200); -} - -.deleteButton:hover { - border-radius: 4px; - color: var(--g2000); - background: var(--g400); -} - -.addLibraryRow { - display: inline-flex; - margin: 1em; - margin-bottom: 0em; - width: 100%; -} - -.addLibraryRow > button { - margin-left: 1em; - margin-right: 1em; -} - -.librariesGrid { - margin-top: 1.5em; - display: grid; - grid-template-columns: max-content 1fr max-content; - grid-auto-flow: row; - gap: 0.4em 0; -} diff --git a/frontend/src/components/Scratch/LibraryPanel.tsx b/frontend/src/components/Scratch/LibraryPanel.tsx deleted file mode 100644 index 2158ef4e..00000000 --- a/frontend/src/components/Scratch/LibraryPanel.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { Fragment, useState } from "react" - -import { useLibraries } from "@/lib/api" -import { Library, TerseScratch } from "@/lib/api/types" -import { TrashIcon } from "@primer/octicons-react" - -import Button from "@/components/Button" -import Select from "@/components/Select2" -import useTranslation from "@/lib/i18n/translate" - -import styles from "./LibraryPanel.module.css" - -type LibrariesT = { - libraries: Library[] -} - -type Props = { - scratch: TerseScratch - onChange: (value: LibrariesT) => void -} - -export default function LibraryPanel({ scratch, onChange }: Props) { - const libraries = useLibraries() - const librariesTranslations = useTranslation("libraries") - - const hasLibrary = libName => scratch.libraries.some(lib => lib.name == libName) - const libraryVersions = scratchlib => { - const lib = libraries.find(lib => lib.name == scratchlib.name) - if (lib != null) { - return lib.supported_versions - } else { - return [scratchlib.version] - } - } - - const addLibrary = libName => { - const lib = libraries.find(lib => lib.name == libName) - if (lib != null) { - return setLibraryVersion(libName, lib.supported_versions[0]) - } - } - const setLibraryVersion = (libName, ver) => { - // clone the libraries - const libs = JSON.parse(JSON.stringify(scratch.libraries)) - // Check if the library is already enabled, if so return it - const scratchlib = scratch.libraries.find(scratchlib => scratchlib.name == libName) - if (scratchlib != null) { - // If it is, set the version - scratchlib.version = ver - } else { - // If it isn't, add the library to the list - libs.push({ name: libName, version: ver }) - } - onChange({ - libraries: libs, - }) - } - const removeLibrary = libName => { - // clone the libraries - let libs = JSON.parse(JSON.stringify(scratch.libraries)) - // Only keep the libs whose name are not libName - libs = libs.filter(lib => lib.name != libName) - onChange({ - libraries: libs, - }) - } - - let librariesSelectOptions = libraries - // Filter out libraries that are already in the scratch - .filter(lib => !scratch.libraries.some(scratchlib => scratchlib.name == lib.name)) - // Turn them into something the Select component accepts. - .map(lib => lib.supported_versions.map(ver => [lib.name, librariesTranslations.t(lib.name)])) - .flat() - - // Prepend a null value to the selector. - const selectOptions = Object.fromEntries([["__NULL__", "---"], ...librariesSelectOptions]) - - const scratchLibraryElements = scratch.libraries.map(lib => - - - - -
- {scratchLibraryElements} -
- - -} diff --git a/frontend/src/components/Scratch/Scratch.tsx b/frontend/src/components/Scratch/Scratch.tsx index b512f12c..63b8cc0d 100644 --- a/frontend/src/components/Scratch/Scratch.tsx +++ b/frontend/src/components/Scratch/Scratch.tsx @@ -21,7 +21,6 @@ import AboutScratch from "./AboutScratch" import DecompilationPanel from "./DecompilePanel" import FamilyPanel from "./FamilyPanel" import useLanguageServer from "./hooks/useLanguageServer" -import LibraryPanel from "./LibraryPanel" import styles from "./Scratch.module.scss" import ScratchMatchBanner from "./ScratchMatchBanner" import ScratchToolbar from "./ScratchToolbar" @@ -34,7 +33,6 @@ enum TabId { DIFF = "scratch_diff", DECOMPILATION = "scratch_decompilation", FAMILY = "scratch_family", - LIBRARIES = "libraries", } const DEFAULT_LAYOUTS: Record<"desktop_2col" | "mobile_2row", Layout> = { @@ -54,7 +52,6 @@ const DEFAULT_LAYOUTS: Record<"desktop_2col" | "mobile_2row", Layout> = { TabId.SOURCE_CODE, TabId.CONTEXT, TabId.OPTIONS, - TabId.LIBRARIES, ], }, { @@ -95,7 +92,6 @@ const DEFAULT_LAYOUTS: Record<"desktop_2col" | "mobile_2row", Layout> = { TabId.SOURCE_CODE, TabId.CONTEXT, TabId.OPTIONS, - TabId.LIBRARIES, ], }, ], @@ -278,10 +274,6 @@ export default function Scratch({ return {() => } - case TabId.LIBRARIES: - return - - default: return } diff --git a/frontend/src/components/compiler/CompilerOpts.module.css b/frontend/src/components/compiler/CompilerOpts.module.css index 785f9250..a5e3a9fa 100644 --- a/frontend/src/components/compiler/CompilerOpts.module.css +++ b/frontend/src/components/compiler/CompilerOpts.module.css @@ -152,3 +152,70 @@ display: block; width: 100%; } + +.library { + display: inline-flex; + flex-direction: row; + + width: 100%; + border-radius: 0.5em; +} + +.libraryName { + cursor: default; + font-size: 0.8rem; + + font-size: 1.0em; + font-weight: 500; + + padding: .5em; + +} + +.librarySelect { + flex-grow: 1; +} + +.deleteButton { + display: flex; + align-items: center; + gap: 4px; + padding: 4px 8px; + + cursor: pointer; + + color: var(--g1900); + background: none; + border: 0; + +} +.deleteButton > svg { + width: 1em; + color: var(--g1200); +} + +.deleteButton:hover { + border-radius: 4px; + color: var(--g2000); + background: var(--g400); +} + +.addLibraryRow { + display: inline-flex; + margin: 1em; + margin-bottom: 0em; + width: 100%; +} + +.addLibraryRow > button { + margin-left: 1em; + margin-right: 1em; +} + +.librariesGrid { + margin-top: 1.5em; + display: grid; + grid-template-columns: max-content 1fr max-content; + grid-auto-flow: row; + gap: 0.4em 0; +} diff --git a/frontend/src/components/compiler/CompilerOpts.tsx b/frontend/src/components/compiler/CompilerOpts.tsx index 5117a1d6..5b3c084c 100644 --- a/frontend/src/components/compiler/CompilerOpts.tsx +++ b/frontend/src/components/compiler/CompilerOpts.tsx @@ -1,9 +1,13 @@ -import { createContext, useContext, ReactElement } from "react" +import { createContext, useContext, useState, Fragment, ReactElement } from "react" import Checkbox from "@/app/(navfooter)/settings/Checkbox" import * as api from "@/lib/api" +import { Library, TerseScratch } from "@/lib/api/types" import useTranslation from "@/lib/i18n/translate" +import { TrashIcon } from "@primer/octicons-react" +import Button from "@/components/Button" +import Select2 from "@/components/Select2" import PlatformIcon from "../PlatformSelect/PlatformIcon" import Select from "../Select" // TODO: use Select2 @@ -149,10 +153,11 @@ function DiffFlags({ schema }: FlagsProps) { } export type CompilerOptsT = { - compiler: string - compiler_flags: string - diff_flags: string[] - preset: string + compiler?: string + compiler_flags?: string + diff_flags?: string[] + preset?: string + libraries?: Library[] } export type Props = { @@ -208,6 +213,10 @@ export default function CompilerOpts({ platform, value, onChange, diffLabel, onD }) } + const setLibraries = (libraries: Library[]) => { + onChange({ libraries }) + } + const optsEditorProvider = { checkFlag(flag: string) { return (" " + opts + " ").includes(" " + flag + " ") @@ -262,6 +271,11 @@ export default function CompilerOpts({ platform, value, onChange, diffLabel, onD + +
+ +
+

Diff options

@@ -354,3 +368,85 @@ export function DiffOptsEditor({ platform, compiler: compilerId, diffLabel, onDi } + +export function LibrariesEditor({ libraries, setLibraries }: { + libraries: Library[] + setLibraries: (libraries: Library[]) => void +}) { + const supportedLibraries = api.useLibraries() + const librariesTranslations = useTranslation("libraries") + + const hasLibrary = libName => libraries.some(lib => lib.name == libName) + const libraryVersions = scratchlib => { + const lib = supportedLibraries.find(lib => lib.name == scratchlib.name) + if (lib != null) { + return lib.supported_versions + } else { + return [scratchlib.version] + } + } + + const addLibrary = libName => { + const lib = supportedLibraries.find(lib => lib.name == libName) + if (lib != null) { + return setLibraryVersion(libName, lib.supported_versions[0]) + } + } + const setLibraryVersion = (libName, ver) => { + // clone the libraries + const libs = JSON.parse(JSON.stringify(libraries)) + // Check if the library is already enabled, if so return it + const scratchlib = libraries.find(scratchlib => scratchlib.name == libName) + if (scratchlib != null) { + // If it is, set the version + scratchlib.version = ver + } else { + // If it isn't, add the library to the list + libs.push({ name: libName, version: ver }) + } + setLibraries(libs) + } + const removeLibrary = libName => { + // clone the libraries + let libs = JSON.parse(JSON.stringify(libraries)) + // Only keep the libs whose name are not libName + libs = libs.filter(lib => lib.name != libName) + setLibraries(libs) + } + + let librariesSelectOptions = supportedLibraries + // Filter out libraries that are already in the scratch + .filter(lib => !libraries.some(scratchlib => scratchlib.name == lib.name)) + // Turn them into something the Select component accepts. + .map(lib => lib.supported_versions.map(ver => [lib.name, librariesTranslations.t(lib.name)])) + .flat() + + // Prepend a null value to the selector. + const selectOptions = Object.fromEntries([["__NULL__", "---"], ...librariesSelectOptions]) + + const scratchLibraryElements = libraries.map(lib => + + setLibraryVersion(lib.name, value)} + options={libraryVersions(lib)} /> + + ) + + const [selectedLib, setSelectedLib] = useState('__NULL__') + + return <> +

Libraries

+
+ + +
+
+ {scratchLibraryElements} +
+ +}