Diff options
@@ -354,3 +369,83 @@ 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 libraryVersions = scratchlib => {
+ const lib = supportedLibraries.find(lib => lib.name == scratchlib.name)
+ if (lib != null) {
+ return Object.fromEntries(lib.supported_versions.map(v => [v, v]))
+ } else {
+ return { [scratchlib.version]: 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)
+ }
+
+ const 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.name, librariesTranslations.t(lib.name)])
+
+ // 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}
+
+ >
+}
diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts
index 6c782ab8..b3f75c44 100644
--- a/frontend/src/lib/api.ts
+++ b/frontend/src/lib/api.ts
@@ -6,7 +6,7 @@ import useSWR, { Revalidator, RevalidatorOptions, mutate } from "swr"
import { useDebouncedCallback } from "use-debounce"
import { ResponseError, get, post, patch, delete_ } from "./api/request"
-import { AnonymousUser, User, Scratch, TerseScratch, Compilation, Page, Compiler, Platform, Project, ProjectMember } from "./api/types"
+import { AnonymousUser, User, Scratch, TerseScratch, Compilation, Page, Compiler, LibraryVersions, Platform, Project, ProjectMember } from "./api/types"
import { ignoreNextWarnBeforeUnload } from "./hooks"
function onErrorRetry(error: ResponseError, key: string, config: C, revalidate: Revalidator, { retryCount }: RevalidatorOptions) {
@@ -82,6 +82,7 @@ export function useSaveScratch(localScratch: Scratch): () => Promise {
name: undefinedIfUnchanged(savedScratch, localScratch, "name"),
description: undefinedIfUnchanged(savedScratch, localScratch, "description"),
match_override: undefinedIfUnchanged(savedScratch, localScratch, "match_override"),
+ libraries: undefinedIfUnchanged(savedScratch, localScratch, "libraries"),
})
await mutate(localScratch.url, updatedScratch, false)
@@ -134,7 +135,8 @@ export function useIsScratchSaved(scratch: Scratch): boolean {
scratch.diff_label === saved.diff_label &&
scratch.source_code === saved.source_code &&
scratch.context === saved.context &&
- scratch.match_override === saved.match_override
+ scratch.match_override === saved.match_override &&
+ JSON.stringify(scratch.libraries) === JSON.stringify(saved.libraries)
)
}
@@ -166,6 +168,7 @@ export function useCompilation(scratch: Scratch | null, autoRecompile = true, au
compiler_flags: scratch.compiler_flags,
diff_flags: scratch.diff_flags,
diff_label: scratch.diff_label,
+ libraries: scratch.libraries,
source_code: scratch.source_code,
context: savedScratch ? undefinedIfUnchanged(savedScratch, scratch, "context") : scratch.context,
}).then((compilation: Compilation) => {
@@ -219,6 +222,7 @@ export function useCompilation(scratch: Scratch | null, autoRecompile = true, au
scratch.compiler,
scratch.compiler_flags, scratch.diff_flags, scratch.diff_label,
scratch.source_code, scratch.context,
+ scratch.libraries,
])
return {
@@ -251,6 +255,16 @@ export function useCompilers(): Record {
return data.compilers
}
+export function useLibraries(): LibraryVersions[] {
+ const { data } = useSWR("/libraries", get, {
+ refreshInterval: 0,
+ suspense: true, // TODO: remove
+ onErrorRetry,
+ })
+
+ return data.libraries
+}
+
export function usePaginated(url: string, firstPage?: Page): {
results: T[]
hasNext: boolean
diff --git a/frontend/src/lib/api/types.ts b/frontend/src/lib/api/types.ts
index 2230a230..a61525de 100644
--- a/frontend/src/lib/api/types.ts
+++ b/frontend/src/lib/api/types.ts
@@ -48,6 +48,7 @@ export interface TerseScratch {
match_override: boolean
project: string
project_function: string
+ libraries: Library[]
}
export interface Scratch extends TerseScratch {
@@ -165,6 +166,16 @@ export type Compiler = {
diff_flags: Flag[]
}
+export type Library = {
+ name: string
+ version: string
+}
+
+export type LibraryVersions = {
+ name: string
+ supported_versions: string[]
+}
+
export type Platform = {
name: string
description: string
diff --git a/frontend/src/lib/i18n/locales/en/libraries.json b/frontend/src/lib/i18n/locales/en/libraries.json
new file mode 100644
index 00000000..f31c29c6
--- /dev/null
+++ b/frontend/src/lib/i18n/locales/en/libraries.json
@@ -0,0 +1,3 @@
+{
+ "directx": "DirectX"
+}
diff --git a/frontend/src/lib/i18n/translate.ts b/frontend/src/lib/i18n/translate.ts
index 59894609..4cb35d21 100644
--- a/frontend/src/lib/i18n/translate.ts
+++ b/frontend/src/lib/i18n/translate.ts
@@ -1,10 +1,17 @@
// Implements a similar API to next-translate but works with app directory
-import translations from "./locales/en/compilers.json"
+import compilersTranslations from "./locales/en/compilers.json"
+import librariesTranslations from "./locales/en/libraries.json"
-export type Section = "compilers"
+const translationsBySection = {
+ "compilers": compilersTranslations,
+ "libraries": librariesTranslations,
+}
+
+export type Section = keyof typeof translationsBySection
export default function useTranslation(section: Section) {
+ const translations = translationsBySection[section]
return {
t(key: string): string {
if (key in translations) {