From 411238ff4022d0b89d40e6b8b0c592fbd5788eb9 Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 19:49:45 -0700 Subject: [PATCH 1/8] add long term countdown option --- lang/en.json | 3 ++- module/config/generalConfig.mjs | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lang/en.json b/lang/en.json index 3f8c4321..e41de0fb 100755 --- a/lang/en.json +++ b/lang/en.json @@ -365,7 +365,8 @@ "toggleSimple": "Toggle Simple View", "types": { "narrative": "Narrative", - "encounter": "Encounter" + "encounter": "Encounter", + "longterm": "Long Term" } }, "CountdownEdit": { diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 3f49f7aa..d8d3a633 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -690,6 +690,10 @@ export const countdownBaseTypes = { encounter: { id: 'encounter', label: 'DAGGERHEART.APPLICATIONS.Countdown.types.encounter' + }, + longterm: { + id: 'longterm', + label: 'DAGGERHEART.APPLICATIONS.Countdown.types.longterm' } }; From e3cda0a9c973019516a2009fa9790d8ae99658fc Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 20:05:04 -0700 Subject: [PATCH 2/8] add show countdown logic --- module/applications/ui/countdowns.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 42920a4a..1ebec9b6 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -15,6 +15,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application super(options); this.setupHooks(); + this._isFocused = false; } /** @inheritDoc */ @@ -139,6 +140,16 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application return context; } + /**Filter countdowns based on focus state */ + #shouldShowCountdown(countdown){ + // Always show narrative and encounter countdowns + if (countdown.type !== CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id){ + return true; + } + // Only show longterm countdowns when focused/hovered + return this._isFocused; + } + static #getPlayerOwnership(user, setting, countdown) { const playerOwnership = countdown.ownership[user.id]; return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT From d16d01c943088299c1e1458ebe4310309826ac5f Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 20:27:31 -0700 Subject: [PATCH 3/8] add fade in/out logic --- module/applications/ui/countdowns.mjs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 1ebec9b6..0ef5329e 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -91,7 +91,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application countdown, ownership: DhCountdowns.#getPlayerOwnership(game.user, setting, countdown) })); - return values.filter(v => v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE); + return values.filter(v => + v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE && + this.#shouldShowCountdown(v.countdown) + ); } /** @override */ @@ -247,6 +250,19 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application setupHooks() { Hooks.on(socketEvent.Refresh, this.cooldownRefresh.bind()); } + #onFocus() { + if (!this._isFocused){ + this._isFocused = true; + this.render() + } + } + + #onBlur() { + if (this._isFocused){ + this._isFocused = false; + this.render() + } + } async close(options) { /* Opt out of Foundry's standard behavior of closing all application windows marked as UI when Escape is pressed */ @@ -302,5 +318,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application if (options?.force) { document.getElementById('ui-right-column-1')?.appendChild(this.element); } + // Hover/focus listeners + this.element.addEventListener('mouseenter', this.#onFocus.bind(this)); + this.element.addEventListener('mouseleave', this.#onBlur.bind(this)); + this.element.addEventListener('focusin', this.#onFocus.bind(this)); + this.element.addEventListener('focusout', this.#onBlur.bind(this)); } } From 5b0b1023f6dcfc0acc6717bd39958904dd647e87 Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 22:00:49 -0700 Subject: [PATCH 4/8] organize countdown --- module/applications/ui/countdowns.mjs | 36 +++++++++++++++++++-------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 0ef5329e..4381012a 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -106,14 +106,18 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) === CONFIG.DH.GENERAL.countdownAppMode.iconOnly; const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns); - context.countdowns = this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => { - const playersWithAccess = game.users.reduce((acc, user) => { - const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown); - if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) { - acc.push(user); - } - return acc; - }, []); + + const allCountdowns = this.#getCountdowns(); + + const { longTermCountdowns, otherCountdowns } = allCountdowns.reduce((acc, { key, countdown, ownership }) => { + const playersWithAccess = game.users.reduce((acc, user) => { + const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown); + if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) { + acc.push(user); + } + return acc; + }, []); + const nonGmPlayers = game.users.filter(x => !x.isGM); const countdownEditable = game.user.isGM || ownership === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER; @@ -129,7 +133,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application !countdownEditable || (isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0')); - acc[key] = { + const countdownData = { ...countdown, editable: countdownEditable, noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0, @@ -137,9 +141,21 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application loopDisabled: isLooping ? loopDisabled : null, loopTooltip: isLooping && game.i18n.localize(loopTooltip) }; + if (countdown.type == CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id){ + if (this._isFocused){ + acc.longTermCountdowns.push([key, countdownData]); + } + } else { + acc.otherCountdowns.push([key, countdownData]) + } + return acc; + }, {longTermCountdowns: [], otherCountdowns: []}); + + // Combine: regular countdowns first, then long-term + context.countdowns = [...otherCountdowns, ...longTermCountdowns].reduce((acc, [key, countdown]) => { + acc[key]=countdown; return acc; }, {}); - return context; } From a02ca40f87a9e46b1ffeec070f6ef475c2ecf316 Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 22:19:24 -0700 Subject: [PATCH 5/8] add indication of long term countdowns --- module/applications/ui/countdowns.mjs | 10 ++++++++-- styles/less/ui/countdown/countdown.less | 16 ++++++++++++++++ templates/ui/countdowns.hbs | 6 ++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index 4381012a..bfb68153 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -92,8 +92,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application ownership: DhCountdowns.#getPlayerOwnership(game.user, setting, countdown) })); return values.filter(v => - v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE && - this.#shouldShowCountdown(v.countdown) + v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE ); } @@ -156,6 +155,13 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application acc[key]=countdown; return acc; }, {}); + context.hasHiddenLongTerm = !this._isFocused && allCountdowns.some( + ({countdown}) => countdown.type === CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id + ); + console.log('Debug - isFocused:', this._isFocused); + console.log('Debug - hasHiddenLongTerm:', context.hasHiddenLongTerm); + console.log('Debug - allCountdowns:', allCountdowns); + console.log('Debug - longterm countdowns:', allCountdowns.filter(({countdown}) => countdown.type === CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id)); return context; } diff --git a/styles/less/ui/countdown/countdown.less b/styles/less/ui/countdown/countdown.less index 47f06eb7..56381a44 100644 --- a/styles/less/ui/countdown/countdown.less +++ b/styles/less/ui/countdown/countdown.less @@ -153,4 +153,20 @@ } } } + .longterm-indicator { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 8px; + margin-top: 8px; + border-top: 1px solid light-dark(@dark-blue-40, @beige-40); + font-size: var(--font-size-12); + color: light-dark(@dark-80, @beige-80); + cursor: default; + + i { + font-size: var(--font-size-10); + } +} } diff --git a/templates/ui/countdowns.hbs b/templates/ui/countdowns.hbs index 18694e49..73cd644f 100644 --- a/templates/ui/countdowns.hbs +++ b/templates/ui/countdowns.hbs @@ -38,5 +38,11 @@ {{/each}} + {{#if hasHiddenLongTerm}} +
+ + Long Term Countdowns +
+ {{/if}} \ No newline at end of file From 06f6771d708eb98b884554fdf69f134c500ba47b Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 22:20:06 -0700 Subject: [PATCH 6/8] . --- module/applications/ui/countdowns.mjs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs index bfb68153..204ef150 100644 --- a/module/applications/ui/countdowns.mjs +++ b/module/applications/ui/countdowns.mjs @@ -158,10 +158,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application context.hasHiddenLongTerm = !this._isFocused && allCountdowns.some( ({countdown}) => countdown.type === CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id ); - console.log('Debug - isFocused:', this._isFocused); - console.log('Debug - hasHiddenLongTerm:', context.hasHiddenLongTerm); - console.log('Debug - allCountdowns:', allCountdowns); - console.log('Debug - longterm countdowns:', allCountdowns.filter(({countdown}) => countdown.type === CONFIG.DH.GENERAL.countdownBaseTypes.longterm.id)); return context; } From 7611f04d086329f2bd2d4000667d37960a0b9d5b Mon Sep 17 00:00:00 2001 From: Psitacus Date: Wed, 7 Jan 2026 22:31:25 -0700 Subject: [PATCH 7/8] add localization --- lang/en.json | 3 ++- styles/less/ui/countdown/countdown.less | 28 ++++++++++++------------- templates/ui/countdowns.hbs | 2 +- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lang/en.json b/lang/en.json index e41de0fb..47406b09 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2661,7 +2661,8 @@ "noPlayerAccess": "This countdown isn't visible to any players", "loop": "Looping", "decreasingLoop": "Decreasing Looping", - "increasingLoop": "Increasing Looping" + "increasingLoop": "Increasing Looping", + "longTermIndicator": "Long Term Countdowns" }, "EffectsDisplay": { "removeThing": "[Right Click] Remove {thing}", diff --git a/styles/less/ui/countdown/countdown.less b/styles/less/ui/countdown/countdown.less index 56381a44..ca17ee86 100644 --- a/styles/less/ui/countdown/countdown.less +++ b/styles/less/ui/countdown/countdown.less @@ -154,19 +154,19 @@ } } .longterm-indicator { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - padding: 8px; - margin-top: 8px; - border-top: 1px solid light-dark(@dark-blue-40, @beige-40); - font-size: var(--font-size-12); - color: light-dark(@dark-80, @beige-80); - cursor: default; - - i { - font-size: var(--font-size-10); + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 8px; + margin-top: 4px; + border-top: 1px solid light-dark(@dark-blue-40, @beige-40); + font-size: var(--font-size-12); + color: light-dark(@dark-80, @beige-80); + cursor: default; + + i { + font-size: var(--font-size-10); + } } } -} diff --git a/templates/ui/countdowns.hbs b/templates/ui/countdowns.hbs index 73cd644f..a7885488 100644 --- a/templates/ui/countdowns.hbs +++ b/templates/ui/countdowns.hbs @@ -41,7 +41,7 @@ {{#if hasHiddenLongTerm}}
- Long Term Countdowns + {{localize "DAGGERHEART.UI.Countdowns.longTermIndicator"}}
{{/if}} From 9ac5923e7754dd1ba60c28f33ae26fdfa1cceaf7 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 10 Jan 2026 01:01:05 +0100 Subject: [PATCH 8/8] Updated SRD cases that should use long-term countdowns --- .../adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json | 6 +++--- .../environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json b/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json index 5320a0ed..aaf6babd 100644 --- a/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json +++ b/src/packs/adversaries/adversary_Monarch_yx0vK2yfNVZKWUUi.json @@ -346,15 +346,15 @@ "countdown": [ { "name": "Casus Belli", - "type": "narrative", + "type": "longterm", "defaultOwnership": -1, "img": "icons/sundries/scrolls/scroll-bound-sealed-red-tan.webp", "progress": { "looping": "noLooping", "type": "custom", - "start": 1, "startFormula": "8", - "current": 1 + "current": 1, + "start": 1 }, "ownership": {} } diff --git a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json index aacf87e9..f34d90b7 100644 --- a/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json +++ b/src/packs/environments/environment_Divine_Usurpation_4DLYez7VbMCFDAuZ.json @@ -180,15 +180,15 @@ "countdown": [ { "name": "Final Preparations", - "type": "encounter", + "type": "longterm", "defaultOwnership": -1, "img": "icons/magic/unholy/hands-circle-light-green.webp", "progress": { "looping": "noLooping", "type": "custom", - "start": 1, "startFormula": "8", - "current": 1 + "current": 1, + "start": 1 }, "ownership": {} }