Let a reader switch off the chores the app invented
Today's dailies carries two different things: each game's standing chore — "Commissions, resin", a fixed list nobody publishes — and any event with a checklist. The first is the app guessing at a routine the reader never asked for, and it was the only part of that strip with no way out. So the switch removes exactly that. Events keep their checklists whatever their source, including ones the reader added themselves and marked daily, which was the requirement most at risk of being filtered away by a switch aimed at something else. Nothing is discarded. The ticks live under `dailies:<game>` and nothing here reads or writes them, so switching back on restores every logged day and every streak — the same promise `detectDaily` already makes. Defaulted on, because everyone has these today and a setting that silently removes something on upgrade is worse than one nobody notices. Gating where the chore is built rather than where it is drawn means the counts follow for free: "N still waiting on you today" is derived from the items, and a game left with nothing contributes no group at all, so the strip's own empty guard drops it rather than leaving a heading with no rows. Named for what it removes. A switch called "dailies" would read as broken while the strip stayed on screen showing the reader's own events. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f324208457
commit
4277c28e50
@@ -30,6 +30,7 @@ const PREFS: Prefs = {
|
||||
showUpcoming: false,
|
||||
timelineSplitUpcoming: true,
|
||||
detectDaily: false,
|
||||
showChores: true,
|
||||
showCompleted: true,
|
||||
showIgnored: false,
|
||||
theme: "dark",
|
||||
@@ -99,11 +100,13 @@ describe("Controls: what am I allowed to look at", () => {
|
||||
|
||||
test("it reads its own preference and not a neighbour's", () => {
|
||||
// Both neighbours are on and this one is off, so a checkbox bound to the
|
||||
// wrong key shows up as the wrong count of ticks.
|
||||
// wrong key shows up as the wrong count of ticks. The chores toggle is a
|
||||
// third box that is on in both renders — it defaults on — so it raises
|
||||
// each count by one without changing what the delta proves.
|
||||
const off = checkboxes(render(PREFS));
|
||||
const on = checkboxes(render({ ...PREFS, showUpcoming: true }));
|
||||
expect(off.filter(Boolean)).toHaveLength(1);
|
||||
expect(on.filter(Boolean)).toHaveLength(2);
|
||||
expect(off.filter(Boolean)).toHaveLength(2);
|
||||
expect(on.filter(Boolean)).toHaveLength(3);
|
||||
});
|
||||
|
||||
test("how unstarted events sit on the board is offered only when they are", () => {
|
||||
|
||||
@@ -1014,3 +1014,77 @@ describe("boardWindow is not widened by expansion", () => {
|
||||
expect(chartWidthOf(withExpand)).toBe(chartWidthOf(withoutExpand));
|
||||
});
|
||||
});
|
||||
|
||||
describe("dailyGroups with the chores switched off", () => {
|
||||
const NOW = Date.parse("2026-08-17T12:00:00.000Z");
|
||||
const meta = (id: string) => metaFor(id, {});
|
||||
const startOf = (e: { startsAt: string }) => Date.parse(e.startsAt);
|
||||
const repeating = (id: string, game: string, title: string) =>
|
||||
({
|
||||
id,
|
||||
game,
|
||||
title,
|
||||
type: "login",
|
||||
summary: null,
|
||||
startsAt: "2026-08-10T00:00:00.000Z",
|
||||
startPrecision: "day",
|
||||
endsAt: null,
|
||||
endPrecision: "unknown",
|
||||
regionScoped: false,
|
||||
regionEnds: null,
|
||||
sourceUrl: "https://example.test",
|
||||
}) as never;
|
||||
|
||||
test("the invented chore goes and the events stay", () => {
|
||||
// Only the fixed per-game list the app makes up goes. Anything with a
|
||||
// checklist is something the reader engaged with, and stays.
|
||||
const groups = dailyGroups(
|
||||
["genshin"],
|
||||
[repeating("e1", "genshin", "Login Bonus")],
|
||||
NOW,
|
||||
"europe",
|
||||
meta,
|
||||
startOf,
|
||||
false,
|
||||
);
|
||||
expect(groups.map((g) => g.items.map((i) => i.key))).toEqual([["e1"]]);
|
||||
});
|
||||
|
||||
test("an event the reader added themselves is untouched", () => {
|
||||
// Stated explicitly because it is the requirement most at risk of being
|
||||
// filtered away by a switch aimed at something else.
|
||||
const groups = dailyGroups(
|
||||
["genshin"],
|
||||
[repeating("myevent:k3f9qa2m01", "genshin", "My own grind")],
|
||||
NOW,
|
||||
"europe",
|
||||
meta,
|
||||
startOf,
|
||||
false,
|
||||
);
|
||||
expect(groups[0]?.items.map((i) => i.key)).toEqual(["myevent:k3f9qa2m01"]);
|
||||
});
|
||||
|
||||
test("with nothing else to show, a game contributes no group at all", () => {
|
||||
// Not an empty group with a heading and no rows — the strip's own
|
||||
// `total === 0` guard then drops it entirely, which is what a reader who
|
||||
// turned this off is asking for.
|
||||
const groups = dailyGroups(["genshin", "hsr"], [], NOW, "europe", meta, startOf, false);
|
||||
expect(groups).toEqual([]);
|
||||
});
|
||||
|
||||
test("left on, nothing about the strip moves", () => {
|
||||
const groups = dailyGroups(
|
||||
["genshin"],
|
||||
[repeating("e1", "genshin", "Login Bonus")],
|
||||
NOW,
|
||||
"europe",
|
||||
meta,
|
||||
startOf,
|
||||
true,
|
||||
);
|
||||
expect(groups.map((g) => g.items.map((i) => i.key))).toEqual([
|
||||
["dailies:genshin", "e1"],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user