Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Seth Posner 2023-02-25 16:50:39 -08:00
commit c585a5d1b1
15 changed files with 48 additions and 20 deletions

View file

@ -49,5 +49,6 @@ const gameComponent = computed(() => {
position: absolute; position: absolute;
min-height: 100%; min-height: 100%;
height: 100%; height: 100%;
color: var(--foreground);
} }
</style> </style>

View file

@ -288,7 +288,7 @@ export function createCollapsibleModifierSections(
return sections; return sections;
} }
const collapsed = persistent<Record<number, boolean>>({}); const collapsed = persistent<Record<number, boolean>>({}, false);
const jsxFunc = jsx(() => { const jsxFunc = jsx(() => {
const sections = calculateSections(); const sections = calculateSections();
@ -389,7 +389,7 @@ export function colorText(textToColor: string, color = "var(--accent2)"): JSX.El
export function createCollapsibleMilestones(milestones: Record<string, GenericMilestone>) { export function createCollapsibleMilestones(milestones: Record<string, GenericMilestone>) {
// Milestones are typically defined from easiest to hardest, and we want to show hardest first // Milestones are typically defined from easiest to hardest, and we want to show hardest first
const orderedMilestones = Object.values(milestones).reverse(); const orderedMilestones = Object.values(milestones).reverse();
const collapseMilestones = persistent<boolean>(true); const collapseMilestones = persistent<boolean>(true, false);
const lockedMilestones = computed(() => const lockedMilestones = computed(() =>
orderedMilestones.filter(m => m.earned.value === false) orderedMilestones.filter(m => m.earned.value === false)
); );

View file

@ -76,7 +76,7 @@ export function createAchievement<T extends AchievementOptions>(
optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>, optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>,
...decorators: Decorator<T, BaseAchievement, GenericAchievement>[] ...decorators: Decorator<T, BaseAchievement, GenericAchievement>[]
): Achievement<T> { ): Achievement<T> {
const earned = persistent<boolean>(false); const earned = persistent<boolean>(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {}); const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => { return createLazyProxy(() => {
const achievement = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); const achievement = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);

View file

@ -208,11 +208,14 @@ export type GenericBoard = Replace<
export function createBoard<T extends BoardOptions>( export function createBoard<T extends BoardOptions>(
optionsFunc: OptionsFunc<T, BaseBoard, GenericBoard> optionsFunc: OptionsFunc<T, BaseBoard, GenericBoard>
): Board<T> { ): Board<T> {
const state = persistent<BoardData>({ const state = persistent<BoardData>(
{
nodes: [], nodes: [],
selectedNode: null, selectedNode: null,
selectedAction: null selectedAction: null
}); },
false
);
return createLazyProxy(() => { return createLazyProxy(() => {
const board = optionsFunc(); const board = optionsFunc();

View file

@ -103,7 +103,7 @@ export function createChallenge<T extends ChallengeOptions>(
...decorators: Decorator<T, BaseChallenge, GenericChallenge>[] ...decorators: Decorator<T, BaseChallenge, GenericChallenge>[]
): Challenge<T> { ): Challenge<T> {
const completions = persistent(0); const completions = persistent(0);
const active = persistent(false); const active = persistent(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {}); const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => { return createLazyProxy(() => {
const challenge = optionsFunc(); const challenge = optionsFunc();

View file

@ -238,7 +238,7 @@ export type GenericGrid = Replace<
export function createGrid<T extends GridOptions>( export function createGrid<T extends GridOptions>(
optionsFunc: OptionsFunc<T, BaseGrid, GenericGrid> optionsFunc: OptionsFunc<T, BaseGrid, GenericGrid>
): Grid<T> { ): Grid<T> {
const cellState = persistent<Record<string | number, State>>({}); const cellState = persistent<Record<string | number, State>>({}, false);
return createLazyProxy(() => { return createLazyProxy(() => {
const grid = optionsFunc(); const grid = optionsFunc();
grid.id = getUniqueID("grid-"); grid.id = getUniqueID("grid-");

View file

@ -58,7 +58,7 @@ export type GenericInfobox = Replace<
export function createInfobox<T extends InfoboxOptions>( export function createInfobox<T extends InfoboxOptions>(
optionsFunc: OptionsFunc<T, BaseInfobox, GenericInfobox> optionsFunc: OptionsFunc<T, BaseInfobox, GenericInfobox>
): Infobox<T> { ): Infobox<T> {
const collapsed = persistent<boolean>(false); const collapsed = persistent<boolean>(false, false);
return createLazyProxy(() => { return createLazyProxy(() => {
const infobox = optionsFunc(); const infobox = optionsFunc();
infobox.id = getUniqueID("infobox-"); infobox.id = getUniqueID("infobox-");

View file

@ -96,7 +96,7 @@ export function createMilestone<T extends MilestoneOptions>(
optionsFunc?: OptionsFunc<T, BaseMilestone, GenericMilestone>, optionsFunc?: OptionsFunc<T, BaseMilestone, GenericMilestone>,
...decorators: Decorator<T, BaseMilestone, GenericMilestone>[] ...decorators: Decorator<T, BaseMilestone, GenericMilestone>[]
): Milestone<T> { ): Milestone<T> {
const earned = persistent<boolean>(false); const earned = persistent<boolean>(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {}); const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => { return createLazyProxy(() => {
const milestone = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); const milestone = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);

View file

@ -50,7 +50,7 @@ export default defineComponent({
const glowColorStyle = computed(() => { const glowColorStyle = computed(() => {
const color = unwrapRef(glowColor); const color = unwrapRef(glowColor);
if (color != null) { if (color == null || color === "") {
return {}; return {};
} }
if (unref(floating)) { if (unref(floating)) {

View file

@ -101,7 +101,7 @@ export function createTabFamily<T extends TabFamilyOptions>(
throw "Cannot create tab family with 0 tabs"; throw "Cannot create tab family with 0 tabs";
} }
const selected = persistent(Object.keys(tabs)[0]); const selected = persistent(Object.keys(tabs)[0], false);
return createLazyProxy(() => { return createLazyProxy(() => {
const tabFamily = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); const tabFamily = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);

View file

@ -78,7 +78,7 @@ export function addTooltip<T extends TooltipOptions>(
options.pinnable = false; options.pinnable = false;
} else { } else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
(element as any).pinned = options.pinned = persistent<boolean>(false); (element as any).pinned = options.pinned = persistent<boolean>(false, false);
} }
} }

View file

@ -89,7 +89,7 @@ export function createUpgrade<T extends UpgradeOptions>(
optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>, optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>,
...decorators: Decorator<T, BaseUpgrade, GenericUpgrade>[] ...decorators: Decorator<T, BaseUpgrade, GenericUpgrade>[]
): Upgrade<T> { ): Upgrade<T> {
const bought = persistent<boolean>(false); const bought = persistent<boolean>(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {}); const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => { return createLazyProxy(() => {
const upgrade = optionsFunc(); const upgrade = optionsFunc();

View file

@ -219,7 +219,7 @@ export function createLayer<T extends LayerOptions>(
addingLayers.push(id); addingLayers.push(id);
persistentRefs[id] = new Set(); persistentRefs[id] = new Set();
layer.minimized = persistent(false); layer.minimized = persistent(false, false);
Object.assign(layer, optionsFunc.call(layer as BaseLayer)); Object.assign(layer, optionsFunc.call(layer as BaseLayer));
if ( if (
addingLayers[addingLayers.length - 1] == null || addingLayers[addingLayers.length - 1] == null ||

View file

@ -40,6 +40,11 @@ export const NonPersistent = Symbol("NonPersistent");
* @see {@link Persistent[SaveDataPath]} * @see {@link Persistent[SaveDataPath]}
*/ */
export const SaveDataPath = Symbol("SaveDataPath"); export const SaveDataPath = Symbol("SaveDataPath");
/**
* A symbol used in {@link Persistent} objects.
* @see {@link Persistent[CheckNaN]}
*/
export const CheckNaN = Symbol("CheckNaN");
/** /**
* This is a union of things that should be safely stringifiable without needing special processes or knowing what to load them in as. * This is a union of things that should be safely stringifiable without needing special processes or knowing what to load them in as.
@ -78,6 +83,10 @@ export type Persistent<T extends State = State> = Ref<T> & {
* The path this persistent appears in within the save data object. Predominantly used to ensure it's only placed in there one time. * The path this persistent appears in within the save data object. Predominantly used to ensure it's only placed in there one time.
*/ */
[SaveDataPath]: string[] | undefined; [SaveDataPath]: string[] | undefined;
/**
* Whether or not to NaN-check this ref. Should only be true on values expected to always be DecimalSources.
*/
[CheckNaN]: boolean;
}; };
export type NonPersistent<T extends State = State> = WritableComputedRef<T> & { [DefaultValue]: T }; export type NonPersistent<T extends State = State> = WritableComputedRef<T> & { [DefaultValue]: T };
@ -115,8 +124,12 @@ function checkNaNAndWrite<T extends State>(persistent: Persistent<T>, value: T)
* Create a persistent ref, which can be saved and loaded. * Create a persistent ref, which can be saved and loaded.
* All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func. * All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func.
* @param defaultValue The value the persistent ref should start at on fresh saves or when reset. * @param defaultValue The value the persistent ref should start at on fresh saves or when reset.
* @param checkNaN Whether or not to check this ref for being NaN on set. Only use on refs that should always be DecimalSources.
*/ */
export function persistent<T extends State>(defaultValue: T | Ref<T>): Persistent<T> { export function persistent<T extends State>(
defaultValue: T | Ref<T>,
checkNaN = true
): Persistent<T> {
const persistentState: Ref<T> = isRef(defaultValue) const persistentState: Ref<T> = isRef(defaultValue)
? defaultValue ? defaultValue
: (ref<T>(defaultValue) as Ref<T>); : (ref<T>(defaultValue) as Ref<T>);
@ -130,7 +143,11 @@ export function persistent<T extends State>(defaultValue: T | Ref<T>): Persisten
return persistentState.value; return persistentState.value;
}, },
set(value) { set(value) {
if (checkNaN) {
checkNaNAndWrite(persistent, value); checkNaNAndWrite(persistent, value);
} else {
persistent[PersistentState].value = value;
}
} }
}) as NonPersistent<T>; }) as NonPersistent<T>;
nonPersistent[DefaultValue] = defaultValue; nonPersistent[DefaultValue] = defaultValue;
@ -141,7 +158,11 @@ export function persistent<T extends State>(defaultValue: T | Ref<T>): Persisten
return persistentState.value as T; return persistentState.value as T;
}, },
set value(value: T) { set value(value: T) {
if (checkNaN) {
checkNaNAndWrite(persistent, value); checkNaNAndWrite(persistent, value);
} else {
persistent[PersistentState].value = value;
}
}, },
__v_isRef: true, __v_isRef: true,
[PersistentState]: persistentState, [PersistentState]: persistentState,

View file

@ -32,6 +32,9 @@ export default defineConfig({
tsconfigPaths(), tsconfigPaths(),
VitePWA({ VitePWA({
includeAssets: ["Logo.svg", "favicon.ico", "robots.txt", "apple-touch-icon.png"], includeAssets: ["Logo.svg", "favicon.ico", "robots.txt", "apple-touch-icon.png"],
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg}']
},
manifest: { manifest: {
name: projInfo.title, name: projInfo.title,
short_name: projInfo.title, short_name: projInfo.title,