mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 14:36:13 +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}?",
|
||||
"OpenOwnership": "Edit Player Ownership",
|
||||
"Title": "{type} Countdowns",
|
||||
"ToggleSimple": "Toggle Simple View",
|
||||
"Types": {
|
||||
"narrative": "Narrative",
|
||||
"encounter": "Encounter"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { countdownTypes } from '../config/generalConfig.mjs';
|
||||
import { GMUpdateEvent, RefreshType, socketEvent } from '../helpers/socket.mjs';
|
||||
import constructHTMLButton from '../helpers/utils.mjs';
|
||||
import OwnershipSelection from './ownershipSelection.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
|
@ -25,14 +26,15 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
frame: true,
|
||||
title: 'Countdowns',
|
||||
resizable: true,
|
||||
minimizable: true
|
||||
minimizable: false
|
||||
},
|
||||
actions: {
|
||||
addCountdown: this.addCountdown,
|
||||
removeCountdown: this.removeCountdown,
|
||||
editImage: this.onEditImage,
|
||||
openOwnership: this.openOwnership,
|
||||
openCountdownOwnership: this.openCountdownOwnership
|
||||
openCountdownOwnership: this.openCountdownOwnership,
|
||||
toggleSimpleView: this.toggleSimpleView
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true }
|
||||
};
|
||||
|
|
@ -53,11 +55,44 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
});
|
||||
}
|
||||
|
||||
async _onFirstRender(context, options) {
|
||||
super._onFirstRender(context, options);
|
||||
async _preFirstRender(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');
|
||||
this.element.querySelector('.minimized-view').classList.toggle('hidden');
|
||||
const viewSetting = game.user.getFlag(SYSTEM.id, SYSTEM.FLAGS.countdown.simple) ?? !game.user.isGM;
|
||||
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) {
|
||||
|
|
@ -67,15 +102,17 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
context.isGM = game.user.isGM;
|
||||
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 = {
|
||||
...countdownData,
|
||||
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
||||
const countdown = countdownData.countdowns[key];
|
||||
|
||||
const ownershipValue = countdown.playerOwnership[game.user.id].value;
|
||||
if (ownershipValue > CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||
acc[key] = { ...countdown, canEdit: ownershipValue === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER };
|
||||
if (this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED, false, countdown)) {
|
||||
acc[key] = {
|
||||
...countdown,
|
||||
canEdit: this.testUserPermission(CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER, true, countdown)
|
||||
};
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
@ -83,7 +120,7 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
};
|
||||
context.systemFields = countdownData.schema.fields;
|
||||
context.countdownFields = context.systemFields.countdowns.element.fields;
|
||||
context.minimized = this.minimized || _options.isFirstRender;
|
||||
context.simple = this.simpleView;
|
||||
|
||||
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) {
|
||||
if (game.user.isGM) {
|
||||
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) {
|
||||
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
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({})
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,10 +225,10 @@ export const getDeleteKeys = (property, innerProperty, innerPropertyDefaultValue
|
|||
|
||||
// Fix on Foundry native formula replacement for DH
|
||||
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 => {
|
||||
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);
|
||||
return nativeReplaceFormulaData(formula, data, { missing, warn });
|
||||
};
|
||||
|
|
@ -258,3 +258,25 @@ export const damageKeyToNumber = key => {
|
|||
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 {
|
||||
.daggerheart.dh-style.countdown {
|
||||
&.minimized .minimized-view .mini-countdown-container {
|
||||
.minimized-view .mini-countdown-container {
|
||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||
}
|
||||
}
|
||||
|
|
@ -26,51 +26,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.minimized {
|
||||
height: auto !important;
|
||||
max-height: unset !important;
|
||||
max-width: 740px !important;
|
||||
width: auto !important;
|
||||
.minimized-view {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.window-content {
|
||||
display: flex;
|
||||
padding: 4px 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.minimized-view {
|
||||
.mini-countdown-container {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
border: 2px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
padding: 0 4px 0 0;
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
color: light-dark(@beige, @dark);
|
||||
cursor: pointer;
|
||||
|
||||
.mini-countdown-container {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border: 2px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
padding: 0 4px 0 0;
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
color: light-dark(@beige, @dark);
|
||||
cursor: pointer;
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
}
|
||||
.mini-countdown-name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mini-countdown-name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mini-countdown-value {
|
||||
}
|
||||
.mini-countdown-value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3386,7 +3386,7 @@ div.daggerheart.views.multiclass {
|
|||
#resources:has(.fear-bar) {
|
||||
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');
|
||||
}
|
||||
.daggerheart.dh-style.countdown {
|
||||
|
|
@ -3406,23 +3406,12 @@ div.daggerheart.views.multiclass {
|
|||
.daggerheart.dh-style.countdown fieldset legend a {
|
||||
text-shadow: none;
|
||||
}
|
||||
.daggerheart.dh-style.countdown.minimized {
|
||||
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 {
|
||||
.daggerheart.dh-style.countdown .minimized-view {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
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;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -3434,15 +3423,15 @@ div.daggerheart.views.multiclass {
|
|||
color: light-dark(#efe6d8, #222);
|
||||
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;
|
||||
}
|
||||
.daggerheart.dh-style.countdown.minimized .minimized-view .mini-countdown-container img {
|
||||
.daggerheart.dh-style.countdown .minimized-view .mini-countdown-container img {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
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;
|
||||
}
|
||||
.daggerheart.dh-style.countdown .hidden {
|
||||
|
|
|
|||
|
|
@ -1,42 +1,45 @@
|
|||
<div>
|
||||
<div class="expanded-view {{#if minimized}}hidden{{/if}}">
|
||||
<div class="countdowns-menu">
|
||||
{{#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}}
|
||||
</div>
|
||||
|
||||
<div class="countdowns-container">
|
||||
{{#if simple}}
|
||||
<div class="minimized-view">
|
||||
{{#each source.countdowns}}
|
||||
<fieldset class="countdown-fieldset">
|
||||
<legend>
|
||||
{{this.name}}
|
||||
{{#if this.canEdit}}<a><i class="fa-solid fa-trash icon-button" data-action="removeCountdown" data-countdown="{{@key}}"></i></a>{{/if}}
|
||||
{{#if @root.isGM}}<a><i class="fa-solid fa-users icon-button" data-action="openCountdownOwnership" data-countdown="{{@key}}" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"></i></a>{{/if}}
|
||||
</legend>
|
||||
|
||||
|
||||
<div class="countdown-container">
|
||||
<img src="{{this.img}}" {{#if this.canEdit}}data-action='editImage'{{else}}class="disabled"{{/if}} data-countdown="{{@key}}" />
|
||||
<div class="countdown-inner-container">
|
||||
{{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true disabled=(not this.canEdit)}}
|
||||
<div class="countdown-value-container">
|
||||
{{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true disabled=(not this.canEdit)}}
|
||||
{{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
{{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<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 class="minimized-view {{#if (not minimized)}}hidden{{/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>
|
||||
{{else}}
|
||||
<div class="expanded-view">
|
||||
<div class="countdowns-menu">
|
||||
{{#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}}
|
||||
</div>
|
||||
|
||||
<div class="countdowns-container">
|
||||
{{#each source.countdowns}}
|
||||
<fieldset class="countdown-fieldset">
|
||||
<legend>
|
||||
{{this.name}}
|
||||
{{#if this.canEdit}}<a><i class="fa-solid fa-trash icon-button" data-action="removeCountdown" data-countdown="{{@key}}"></i></a>{{/if}}
|
||||
{{#if @root.isGM}}<a><i class="fa-solid fa-users icon-button" data-action="openCountdownOwnership" data-countdown="{{@key}}" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"></i></a>{{/if}}
|
||||
</legend>
|
||||
|
||||
|
||||
<div class="countdown-container">
|
||||
<img src="{{this.img}}" {{#if this.canEdit}}data-action='editImage'{{else}}class="disabled"{{/if}} data-countdown="{{@key}}" />
|
||||
<div class="countdown-inner-container">
|
||||
{{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true disabled=(not this.canEdit)}}
|
||||
<div class="countdown-value-container">
|
||||
{{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true disabled=(not this.canEdit)}}
|
||||
{{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
{{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue