mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-10 19:17:09 +01:00
Improved
This commit is contained in:
parent
a1f7e0d2c5
commit
3462b3bd77
8 changed files with 159 additions and 131 deletions
|
|
@ -1087,6 +1087,7 @@
|
||||||
"RemoveCountdownText": "Are you sure you want to remove the countdown: {name}?",
|
"RemoveCountdownText": "Are you sure you want to remove the countdown: {name}?",
|
||||||
"OpenOwnership": "Edit Player Ownership",
|
"OpenOwnership": "Edit Player Ownership",
|
||||||
"Title": "{type} Countdowns",
|
"Title": "{type} Countdowns",
|
||||||
|
"ToggleSimple": "Toggle Simple View",
|
||||||
"Types": {
|
"Types": {
|
||||||
"narrative": "Narrative",
|
"narrative": "Narrative",
|
||||||
"encounter": "Encounter"
|
"encounter": "Encounter"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { countdownTypes } from '../config/generalConfig.mjs';
|
import { countdownTypes } from '../config/generalConfig.mjs';
|
||||||
import { GMUpdateEvent, RefreshType, socketEvent } from '../helpers/socket.mjs';
|
import { GMUpdateEvent, RefreshType, socketEvent } from '../helpers/socket.mjs';
|
||||||
|
import constructHTMLButton from '../helpers/utils.mjs';
|
||||||
import OwnershipSelection from './ownershipSelection.mjs';
|
import OwnershipSelection from './ownershipSelection.mjs';
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
@ -25,14 +26,15 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
frame: true,
|
frame: true,
|
||||||
title: 'Countdowns',
|
title: 'Countdowns',
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minimizable: true
|
minimizable: false
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addCountdown: this.addCountdown,
|
addCountdown: this.addCountdown,
|
||||||
removeCountdown: this.removeCountdown,
|
removeCountdown: this.removeCountdown,
|
||||||
editImage: this.onEditImage,
|
editImage: this.onEditImage,
|
||||||
openOwnership: this.openOwnership,
|
openOwnership: this.openOwnership,
|
||||||
openCountdownOwnership: this.openCountdownOwnership
|
openCountdownOwnership: this.openCountdownOwnership,
|
||||||
|
toggleSimpleView: this.toggleSimpleView
|
||||||
},
|
},
|
||||||
form: { handler: this.updateData, submitOnChange: true }
|
form: { handler: this.updateData, submitOnChange: true }
|
||||||
};
|
};
|
||||||
|
|
@ -53,11 +55,44 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onFirstRender(context, options) {
|
async _preFirstRender(context, options) {
|
||||||
super._onFirstRender(context, options);
|
options.position =
|
||||||
|
game.user.getFlag(SYSTEM.id, SYSTEM.FLAGS.countdown.position) ?? Countdowns.DEFAULT_OPTIONS.position;
|
||||||
|
|
||||||
this.element.querySelector('.expanded-view').classList.toggle('hidden');
|
const viewSetting = game.user.getFlag(SYSTEM.id, SYSTEM.FLAGS.countdown.simple) ?? !game.user.isGM;
|
||||||
this.element.querySelector('.minimized-view').classList.toggle('hidden');
|
this.simpleView =
|
||||||
|
game.user.isGM || !this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER) ? viewSetting : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPosition(position) {
|
||||||
|
game.user.setFlag(SYSTEM.id, SYSTEM.FLAGS.countdown.position, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _renderFrame(options) {
|
||||||
|
const frame = await super._renderFrame(options);
|
||||||
|
|
||||||
|
if (this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER)) {
|
||||||
|
const button = constructHTMLButton({
|
||||||
|
label: '',
|
||||||
|
classes: ['header-control', 'icon', 'fa-solid', 'fa-wrench'],
|
||||||
|
dataset: { action: 'toggleSimpleView', tooltip: 'DAGGERHEART.Countdown.ToggleSimple' }
|
||||||
|
});
|
||||||
|
this.window.controls.after(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
testUserPermission(level, exact, altSettings) {
|
||||||
|
if (game.user.isGM) return true;
|
||||||
|
|
||||||
|
const settings =
|
||||||
|
altSettings ?? game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
||||||
|
const defaultAllowed = exact ? settings.ownership.default === level : settings.ownership.default >= level;
|
||||||
|
const userAllowed = exact
|
||||||
|
? settings.playerOwnership[game.user.id]?.value === level
|
||||||
|
: settings.playerOwnership[game.user.id]?.value >= level;
|
||||||
|
return defaultAllowed || userAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _prepareContext(_options) {
|
async _prepareContext(_options) {
|
||||||
|
|
@ -67,15 +102,17 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
context.isGM = game.user.isGM;
|
context.isGM = game.user.isGM;
|
||||||
context.base = this.basePath;
|
context.base = this.basePath;
|
||||||
|
|
||||||
context.canCreate = countdownData.playerOwnership[game.user.id].value === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
context.canCreate = this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER, true);
|
||||||
context.source = {
|
context.source = {
|
||||||
...countdownData,
|
...countdownData,
|
||||||
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
||||||
const countdown = countdownData.countdowns[key];
|
const countdown = countdownData.countdowns[key];
|
||||||
|
|
||||||
const ownershipValue = countdown.playerOwnership[game.user.id].value;
|
if (this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED, false, countdown)) {
|
||||||
if (ownershipValue > CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
acc[key] = {
|
||||||
acc[key] = { ...countdown, canEdit: ownershipValue === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER };
|
...countdown,
|
||||||
|
canEdit: this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER, true, countdown)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|
@ -83,7 +120,7 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
};
|
};
|
||||||
context.systemFields = countdownData.schema.fields;
|
context.systemFields = countdownData.schema.fields;
|
||||||
context.countdownFields = context.systemFields.countdowns.element.fields;
|
context.countdownFields = context.systemFields.countdowns.element.fields;
|
||||||
context.minimized = this.minimized || _options.isFirstRender;
|
context.simple = this.simpleView;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -110,28 +147,6 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async minimize() {
|
|
||||||
await super.minimize();
|
|
||||||
|
|
||||||
this.element.querySelector('.expanded-view').classList.toggle('hidden');
|
|
||||||
this.element.querySelector('.minimized-view').classList.toggle('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
async maximize() {
|
|
||||||
if (this.minimized) {
|
|
||||||
const settings = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
|
||||||
if (settings.playerOwnership[game.user.id].value <= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED) {
|
|
||||||
ui.notifications.info(game.i18n.localize('DAGGERHEART.Countdown.Notifications.LimitedOwnership'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.element.querySelector('.expanded-view').classList.toggle('hidden');
|
|
||||||
this.element.querySelector('.minimized-view').classList.toggle('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
await super.maximize();
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateSetting(update) {
|
async updateSetting(update) {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, update);
|
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, update);
|
||||||
|
|
@ -213,11 +228,17 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toggleSimpleView() {
|
||||||
|
this.simpleView = !this.simpleView;
|
||||||
|
game.user.setFlag(SYSTEM.id, SYSTEM.FLAGS.countdown.simple, this.simpleView);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
async updateCountdownValue(event, increase) {
|
async updateCountdownValue(event, increase) {
|
||||||
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||||
const countdown = countdownSetting[this.basePath].countdowns[event.currentTarget.dataset.countdown];
|
const countdown = countdownSetting[this.basePath].countdowns[event.currentTarget.dataset.countdown];
|
||||||
|
|
||||||
if (countdown.playerOwnership[game.user.id] < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
if (!this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
export const displayDomainCardsAsList = 'displayDomainCardsAsList';
|
export const displayDomainCardsAsList = 'displayDomainCardsAsList';
|
||||||
|
export const countdown = {
|
||||||
|
simple: 'countdown-simple',
|
||||||
|
position: 'countdown-position'
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ class DhCountdownData extends foundry.abstract.DataModel {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
}),
|
||||||
|
window: new fields.SchemaField({})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,8 @@ export const getDeleteKeys = (property, innerProperty, innerPropertyDefaultValue
|
||||||
const nativeReplaceFormulaData = Roll.replaceFormulaData;
|
const nativeReplaceFormulaData = Roll.replaceFormulaData;
|
||||||
Roll.replaceFormulaData = function (formula, data = {}, { missing, warn = false } = {}) {
|
Roll.replaceFormulaData = function (formula, data = {}, { missing, warn = false } = {}) {
|
||||||
const terms = Object.keys(SYSTEM.GENERAL.multiplierTypes).map(type => {
|
const terms = Object.keys(SYSTEM.GENERAL.multiplierTypes).map(type => {
|
||||||
return { term: type, default: 1}
|
return { term: type, default: 1 };
|
||||||
})
|
});
|
||||||
formula = terms.reduce((a, c) => a.replaceAll(`@${c.term}`, data[c.term] ?? c.default), formula);
|
formula = terms.reduce((a, c) => a.replaceAll(`@${c.term}`, data[c.term] ?? c.default), formula);
|
||||||
return nativeReplaceFormulaData(formula, data, { missing, warn });
|
return nativeReplaceFormulaData(formula, data, { missing, warn });
|
||||||
};
|
};
|
||||||
|
|
@ -258,3 +258,25 @@ export const damageKeyToNumber = key => {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default function constructHTMLButton({
|
||||||
|
label,
|
||||||
|
dataset = {},
|
||||||
|
classes = [],
|
||||||
|
icon = '',
|
||||||
|
type = 'button',
|
||||||
|
disabled = false
|
||||||
|
}) {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.type = type;
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(dataset)) {
|
||||||
|
button.dataset[key] = value;
|
||||||
|
}
|
||||||
|
button.classList.add(...classes);
|
||||||
|
if (icon) icon = `<i class="${icon}"></i> `;
|
||||||
|
if (disabled) button.disabled = true;
|
||||||
|
button.innerHTML = `${icon}${label}`;
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
.theme-light {
|
.theme-light {
|
||||||
.daggerheart.dh-style.countdown {
|
.daggerheart.dh-style.countdown {
|
||||||
&.minimized .minimized-view .mini-countdown-container {
|
.minimized-view .mini-countdown-container {
|
||||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,18 +26,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.minimized {
|
|
||||||
height: auto !important;
|
|
||||||
max-height: unset !important;
|
|
||||||
max-width: 740px !important;
|
|
||||||
width: auto !important;
|
|
||||||
|
|
||||||
.window-content {
|
|
||||||
display: flex;
|
|
||||||
padding: 4px 8px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.minimized-view {
|
.minimized-view {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
@ -73,7 +61,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
||||||
|
|
@ -3386,7 +3386,7 @@ div.daggerheart.views.multiclass {
|
||||||
#resources:has(.fear-bar) {
|
#resources:has(.fear-bar) {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
.theme-light .daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container {
|
.theme-light .daggerheart.dh-style.countdown .minimized-view .mini-countdown-container {
|
||||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown {
|
.daggerheart.dh-style.countdown {
|
||||||
|
|
@ -3406,23 +3406,12 @@ div.daggerheart.views.multiclass {
|
||||||
.daggerheart.dh-style.countdown fieldset legend a {
|
.daggerheart.dh-style.countdown fieldset legend a {
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown.minimized {
|
.daggerheart.dh-style.countdown .minimized-view {
|
||||||
height: auto !important;
|
|
||||||
max-height: unset !important;
|
|
||||||
max-width: 740px !important;
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
.daggerheart.dh-style.countdown.minimized .window-content {
|
|
||||||
display: flex;
|
|
||||||
padding: 4px 8px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.daggerheart.dh-style.countdown.minimized .minimized-view {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container {
|
.daggerheart.dh-style.countdown .minimized-view .mini-countdown-container {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -3434,15 +3423,15 @@ div.daggerheart.views.multiclass {
|
||||||
color: light-dark(#efe6d8, #222);
|
color: light-dark(#efe6d8, #222);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container.disabled {
|
.daggerheart.dh-style.countdown .minimized-view .mini-countdown-container.disabled {
|
||||||
cursor: initial;
|
cursor: initial;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container img {
|
.daggerheart.dh-style.countdown .minimized-view .mini-countdown-container img {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
border-radius: 6px 0 0 6px;
|
border-radius: 6px 0 0 6px;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container .mini-countdown-name {
|
.daggerheart.dh-style.countdown .minimized-view .mini-countdown-container .mini-countdown-name {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.daggerheart.dh-style.countdown .hidden {
|
.daggerheart.dh-style.countdown .hidden {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="expanded-view {{#if minimized}}hidden{{/if}}">
|
{{#if simple}}
|
||||||
|
<div class="minimized-view">
|
||||||
|
{{#each source.countdowns}}
|
||||||
|
<a class="mini-countdown-container {{#if (not this.canEdit)}}disabled{{/if}}" data-countdown="{{@key}}">
|
||||||
|
<img src="{{this.img}}" />
|
||||||
|
<div class="mini-countdown-name">{{this.name}}</div>
|
||||||
|
<div class="mini-countdown-value">{{this.progress.current}}/{{this.progress.max}}</div>
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="expanded-view">
|
||||||
<div class="countdowns-menu">
|
<div class="countdowns-menu">
|
||||||
{{#if canCreate}}<button class="flex" data-action="addCountdown">{{localize "DAGGERHEART.Countdown.AddCountdown"}}</button>{{/if}}
|
{{#if canCreate}}<button class="flex" data-action="addCountdown">{{localize "DAGGERHEART.Countdown.AddCountdown"}}</button>{{/if}}
|
||||||
{{#if isGM}}<button data-action="openOwnership" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"><i class="fa-solid fa-users"></i></button>{{/if}}
|
{{#if isGM}}<button data-action="openOwnership" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"><i class="fa-solid fa-users"></i></button>{{/if}}
|
||||||
|
|
@ -30,13 +41,5 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="minimized-view {{#if (not minimized)}}hidden{{/if}}">
|
{{/if}}
|
||||||
{{#each source.countdowns}}
|
|
||||||
<a class="mini-countdown-container {{#if (not this.canEdit)}}disabled{{/if}}" data-countdown="{{@key}}">
|
|
||||||
<img src="{{this.img}}" />
|
|
||||||
<div class="mini-countdown-name">{{this.name}}</div>
|
|
||||||
<div class="mini-countdown-value">{{this.progress.current}}/{{this.progress.max}}</div>
|
|
||||||
</a>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue