Have features register settings fields dynamically

This commit is contained in:
thepaperpilot 2022-02-27 16:41:39 -06:00
parent a81040d6a2
commit 5beecba267
5 changed files with 53 additions and 17 deletions

View file

@ -7,9 +7,9 @@
</template> </template>
<template v-slot:body> <template v-slot:body>
<Select title="Theme" :options="themes" v-model="theme" /> <Select title="Theme" :options="themes" v-model="theme" />
<Select title="Show Milestones" :options="msDisplayOptions" v-model="msDisplay" /> <component :is="settingFieldsComponent" />
<Toggle title="Show TPS" v-model="showTPS" /> <Toggle title="Show TPS" v-model="showTPS" />
<Toggle title="Hide Maxed Challenges" v-model="hideChallenges" /> <hr />
<Toggle title="Unthrottled" v-model="unthrottled" /> <Toggle title="Unthrottled" v-model="unthrottled" />
<Toggle :title="offlineProdTitle" v-model="offlineProd" /> <Toggle :title="offlineProdTitle" v-model="offlineProd" />
<Toggle :title="autosaveTitle" v-model="autosave" /> <Toggle :title="autosaveTitle" v-model="autosave" />
@ -21,15 +21,15 @@
<script setup lang="tsx"> <script setup lang="tsx">
import Modal from "@/components/Modal.vue"; import Modal from "@/components/Modal.vue";
import rawThemes from "@/data/themes"; import rawThemes from "@/data/themes";
import { MilestoneDisplay } from "@/features/milestones/milestone";
import player from "@/game/player"; import player from "@/game/player";
import settings from "@/game/settings"; import settings, { settingFields } from "@/game/settings";
import { camelToTitle } from "@/util/common"; import { camelToTitle } from "@/util/common";
import { computed, ref, toRefs } from "vue"; import { computed, ref, toRefs } from "vue";
import Toggle from "./fields/Toggle.vue"; import Toggle from "./fields/Toggle.vue";
import Select from "./fields/Select.vue"; import Select from "./fields/Select.vue";
import Tooltip from "./Tooltip.vue"; import Tooltip from "./Tooltip.vue";
import { jsx } from "@/features/feature"; import { jsx } from "@/features/feature";
import { coerceComponent, render } from "@/util/vue";
const isOpen = ref(false); const isOpen = ref(false);
@ -44,13 +44,11 @@ const themes = Object.keys(rawThemes).map(theme => ({
value: theme value: theme
})); }));
// TODO allow features to register options const settingFieldsComponent = computed(() => {
const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({ return coerceComponent(jsx(() => <>{settingFields.map(render)}</>));
label: camelToTitle(option), });
value: option
}));
const { showTPS, hideChallenges, theme, msDisplay, unthrottled } = toRefs(settings); const { showTPS, theme, unthrottled } = toRefs(settings);
const { autosave, offlineProd } = toRefs(player); const { autosave, offlineProd } = toRefs(player);
const isPaused = computed({ const isPaused = computed({
get() { get() {

View file

@ -1,9 +1,11 @@
import Toggle from "@/components/fields/Toggle.vue";
import ChallengeComponent from "@/features/challenges/Challenge.vue"; import ChallengeComponent from "@/features/challenges/Challenge.vue";
import { import {
CoercableComponent, CoercableComponent,
Component, Component,
GatherProps, GatherProps,
getUniqueID, getUniqueID,
jsx,
Replace, Replace,
setDefault, setDefault,
StyleValue, StyleValue,
@ -12,8 +14,8 @@ import {
import { GenericReset } from "@/features/reset"; import { GenericReset } from "@/features/reset";
import { Resource } from "@/features/resources/resource"; import { Resource } from "@/features/resources/resource";
import { globalBus } from "@/game/events"; import { globalBus } from "@/game/events";
import { PersistentRef, persistent } from "@/game/persistence"; import { persistent, PersistentRef } from "@/game/persistence";
import settings from "@/game/settings"; import settings, { registerSettingField } from "@/game/settings";
import Decimal, { DecimalSource } from "@/util/bignum"; import Decimal, { DecimalSource } from "@/util/bignum";
import { import {
Computable, Computable,
@ -258,3 +260,13 @@ declare module "@/game/settings" {
globalBus.on("loadSettings", settings => { globalBus.on("loadSettings", settings => {
setDefault(settings, "hideChallenges", false); setDefault(settings, "hideChallenges", false);
}); });
registerSettingField(
jsx(() => (
<Toggle
title="Hide Maxed Challenges"
onUpdate:modelValue={value => (settings.hideChallenges = value)}
modelValue={settings.hideChallenges}
/>
))
);

View file

@ -1,18 +1,22 @@
import MilestoneComponent from "@/features/milestones/Milestone.vue"; import Select from "@/components/fields/Select.vue";
import { import {
CoercableComponent, CoercableComponent,
Component, Component,
findFeatures, findFeatures,
GatherProps, GatherProps,
getUniqueID, getUniqueID,
jsx,
Replace, Replace,
setDefault, setDefault,
StyleValue, StyleValue,
Visibility Visibility
} from "@/features/feature"; } from "@/features/feature";
import MilestoneComponent from "@/features/milestones/Milestone.vue";
import { globalBus } from "@/game/events"; import { globalBus } from "@/game/events";
import "@/game/notifications"; import "@/game/notifications";
import settings from "@/game/settings"; import { makePersistent, Persistent, PersistentState } from "@/game/persistence";
import settings, { registerSettingField } from "@/game/settings";
import { camelToTitle } from "@/util/common";
import { import {
Computable, Computable,
GetComputableType, GetComputableType,
@ -25,7 +29,6 @@ import { coerceComponent, isCoercableComponent } from "@/util/vue";
import { Unsubscribe } from "nanoevents"; import { Unsubscribe } from "nanoevents";
import { computed, Ref, unref } from "vue"; import { computed, Ref, unref } from "vue";
import { useToast } from "vue-toastification"; import { useToast } from "vue-toastification";
import { Persistent, makePersistent, PersistentState } from "@/game/persistence";
export const MilestoneType = Symbol("Milestone"); export const MilestoneType = Symbol("Milestone");
@ -186,3 +189,19 @@ declare module "@/game/settings" {
globalBus.on("loadSettings", settings => { globalBus.on("loadSettings", settings => {
setDefault(settings, "msDisplay", MilestoneDisplay.All); setDefault(settings, "msDisplay", MilestoneDisplay.All);
}); });
const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({
label: camelToTitle(option),
value: option
}));
registerSettingField(
jsx(() => (
<Select
title="Show Milestones"
options={msDisplayOptions}
onUpdate:modelValue={value => (settings.msDisplay = value as MilestoneDisplay)}
modelValue={settings.msDisplay}
/>
))
);

View file

@ -1,5 +1,6 @@
import modInfo from "@/data/modInfo.json"; import modInfo from "@/data/modInfo.json";
import { Themes } from "@/data/themes"; import { Themes } from "@/data/themes";
import { CoercableComponent } from "@/features/feature";
import { globalBus } from "@/game/events"; import { globalBus } from "@/game/events";
import { hardReset } from "@/util/save"; import { hardReset } from "@/util/save";
import { reactive, watch } from "vue"; import { reactive, watch } from "vue";
@ -53,3 +54,9 @@ export const hardResetSettings = (window.hardResetSettings = () => {
Object.assign(state, settings); Object.assign(state, settings);
hardReset(); hardReset();
}); });
export const settingFields: CoercableComponent[] = reactive([]);
export function registerSettingField(component: CoercableComponent) {
settingFields.push(component);
}

View file

@ -62,11 +62,11 @@ export function render(object: VueFeature | CoercableComponent): JSX.Element | D
} }
export function renderRow(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { export function renderRow(...objects: (VueFeature | CoercableComponent)[]): JSX.Element {
return <Row>{objects.map(obj => render(obj))}</Row>; return <Row>{objects.map(render)}</Row>;
} }
export function renderCol(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { export function renderCol(...objects: (VueFeature | CoercableComponent)[]): JSX.Element {
return <Col>{objects.map(obj => render(obj))}</Col>; return <Col>{objects.map(render)}</Col>;
} }
export function isCoercableComponent(component: unknown): component is CoercableComponent { export function isCoercableComponent(component: unknown): component is CoercableComponent {