forked from profectus/Profectus
Have features register settings fields dynamically
This commit is contained in:
parent
a81040d6a2
commit
5beecba267
5 changed files with 53 additions and 17 deletions
|
@ -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() {
|
||||||
|
|
|
@ -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}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
);
|
|
@ -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}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue