Scenario generator for vore roleplay and story ideas. https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
vore-scenario-generator/src/common/client/MainGeneratorOnly.tsx

93 lines
3.2 KiB

import { GeneratorPage, GeneratorSelect, IncludesGenerator } from './GeneratorPage';
import { PageFooter } from './PageFooter';
import type { GeneratedElementProps } from './GeneratedElement';
import { useCallback, useMemo, useState } from 'preact/hooks';
import { ExportFormat, exportScenario, RollSelections, type RollTable, type RollTableResult } from '../rolltable';
export interface GeneratorMainProps {
editable: boolean
generatorTargetUrl: string
addToDiscordUrl: string
creditsUrl: string
initialResults: ReadonlyMap<RollTable, RollTableResult>
initialSelected?: ReadonlySet<RollTable>
}
export interface GeneratorMainEvents {
copyText?: (text: string) => Promise<void>
}
// TODO: add a "reconstitute" function for MainGeneratorOnly
// TODO: add the other two top-level pages (MainResponsesOnly, MainGeneratorResponses) with "reconstitute" functions
// TODO: add the entry points that reconstitute and hydrate each of the respective top-level pages
function MainGeneratorOnly({
editable, generatorTargetUrl, addToDiscordUrl,
creditsUrl, initialResults, initialSelected, copyText}: GeneratorMainProps & GeneratorMainEvents) {
const [results, ] =
useState<ReadonlyMap<RollTable, RollTableResult>>(initialResults)
const [selected, setSelected] =
useState<ReadonlySet<RollTable>|null>(initialSelected ?? null)
const onCopy = useCallback(async (format: ExportFormat) => {
if (!copyText) {
return Promise.reject(Error("Copy functionality is not implemented"))
}
return copyText(exportScenario(Array.from(results.values()), format))
}, [copyText, results])
const onSelectionChange = useCallback((tableId: number, state: boolean) => {
const table = Array.from(initialResults.keys()).find(table => table.full && table.id === tableId)
if (!table) {
return
}
const newSelection = new RollSelections(selected)
if (state) {
newSelection.add(table)
} else {
newSelection.delete(table)
}
setSelected(newSelection)
}, [initialResults, selected, setSelected])
const onSelect = useCallback((select: GeneratorSelect) => {
switch (select) {
case GeneratorSelect.All:
setSelected(new RollSelections(initialResults.keys()));
break;
case GeneratorSelect.None:
setSelected(new RollSelections());
break;
}
}, [initialResults, setSelected])
const elements = useMemo(() => {
const output: GeneratedElementProps[] = []
for (const result of results.values()) {
if (result.full) {
output.push({
...result,
selected: selected === null ? null : selected.has(result.table)
})
} else {
output.push({
...result,
selected: null,
})
}
}
return output
}, [results, selected])
return <IncludesGenerator.Provider value={true}>
<GeneratorPage
generatorTargetUrl={generatorTargetUrl}
elements={elements}
addToDiscordUrl={addToDiscordUrl}
editable={editable}
onCopy={onCopy}
// TODO: implement onReroll using JSON fetch
// specifically: POST to the target URL as if you're submitting the form,
// _but_ add Accept: text/json to indicate you want it for API purposes and not as a page
onSelect={selected ? onSelect : undefined}
onSelectionChange={selected ? onSelectionChange : undefined} />
<PageFooter creditsUrl={creditsUrl} />
</IncludesGenerator.Provider>
}