From d71997a5086af76445a0758573d40c05a6d38a90 Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 8 Dec 2025 23:43:24 -0700 Subject: [PATCH 01/13] Restructure the dev settings so that other categories can be more easily created --- module/apps/DevSettingsMenu.mjs | 3 ++- module/settings/addGlobalDocReferrer.mjs | 2 +- module/settings/autoUnpauseOnLoad.mjs | 2 +- module/utils/DevSettings.mjs | 9 --------- module/utils/SubMenuSettings.mjs | 22 ++++++++++++++++++++++ 5 files changed, 26 insertions(+), 12 deletions(-) delete mode 100644 module/utils/DevSettings.mjs create mode 100644 module/utils/SubMenuSettings.mjs diff --git a/module/apps/DevSettingsMenu.mjs b/module/apps/DevSettingsMenu.mjs index 909fbab..81a14e8 100644 --- a/module/apps/DevSettingsMenu.mjs +++ b/module/apps/DevSettingsMenu.mjs @@ -1,4 +1,4 @@ -import { devSettings } from "../utils/DevSettings.mjs"; +import { categories } from "../utils/SubMenuSettings.mjs"; import { OFTSettingsMenu } from "./OFTSettingsMenu.mjs"; export class DevSettingsMenu extends OFTSettingsMenu { @@ -9,6 +9,7 @@ export class DevSettingsMenu extends OFTSettingsMenu { }; static get _SETTINGS() { + const devSettings = categories.get(`dev`); const settingIDs = []; for (const [settingID, shown] of devSettings.entries()) { if (shown) { diff --git a/module/settings/addGlobalDocReferrer.mjs b/module/settings/addGlobalDocReferrer.mjs index 0700606..d40b1eb 100644 --- a/module/settings/addGlobalDocReferrer.mjs +++ b/module/settings/addGlobalDocReferrer.mjs @@ -1,6 +1,6 @@ import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; -import { registerDevSetting } from "../utils/DevSettings.mjs"; +import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; const key = `addGlobalDocReferrer`; diff --git a/module/settings/autoUnpauseOnLoad.mjs b/module/settings/autoUnpauseOnLoad.mjs index 03ddea4..9bf84b3 100644 --- a/module/settings/autoUnpauseOnLoad.mjs +++ b/module/settings/autoUnpauseOnLoad.mjs @@ -1,6 +1,6 @@ import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; -import { registerDevSetting } from "../utils/DevSettings.mjs"; +import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; const key = `autoUnpauseOnLoad`; diff --git a/module/utils/DevSettings.mjs b/module/utils/DevSettings.mjs deleted file mode 100644 index 7d847fa..0000000 --- a/module/utils/DevSettings.mjs +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {Map} */ -export const devSettings = new Map(); - -export function registerDevSetting(namespace, key, config) { - const visible = config.config; - config.config = false; - game.settings.register(namespace, key, config); - devSettings.set(`${namespace}.${key}`, visible); -}; diff --git a/module/utils/SubMenuSettings.mjs b/module/utils/SubMenuSettings.mjs new file mode 100644 index 0000000..77d73f9 --- /dev/null +++ b/module/utils/SubMenuSettings.mjs @@ -0,0 +1,22 @@ +/** @type {Map>} */ +export const categories = new Map(); + +export function registerCategorySetting(category, namespace, key, config) { + let cat = categories.get(category); + if (!cat) { + cat = new Map(); + categories.set(category, cat); + }; + const visible = config.config; + config.config = false; + game.settings.register(namespace, key, config); + cat.set(`${namespace}.${key}`, visible); +}; + +/** + * A helper function that registers the setting to the "dev" + * category + */ +export function registerDevSetting(namespace, key, config) { + registerCategorySetting(`dev`, namespace, key, config); +}; From 03330973d7e092be1b4380f5e8047c71fb158509 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 19:59:21 -0700 Subject: [PATCH 02/13] Group all of the hotbar settings into a submenu (closes #15) --- langs/en-ca.json | 5 +++++ module/apps/HotbarSettingsMenu.mjs | 21 +++++++++++++++++++++ module/oft.mjs | 15 ++++++++++++--- module/settings/hotbarButtonGap.mjs | 3 ++- module/settings/hotbarButtonSize.mjs | 3 ++- module/settings/repositionHotbar.mjs | 3 ++- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 module/apps/HotbarSettingsMenu.mjs diff --git a/langs/en-ca.json b/langs/en-ca.json index fc4f428..a182d15 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -46,6 +46,11 @@ "name": "Developer Settings", "hint": "Tweaks that are relevant if you are developing something within Foundry, but are rarely useful outside of that context.", "label": "Configure Dev Settings" + }, + "hotbarSettings": { + "name": "Hotbar Settings", + "hint": "Tweaks that modify Foundry's hotbar", + "label": "Configure Hotbar" } }, "apps": { diff --git a/module/apps/HotbarSettingsMenu.mjs b/module/apps/HotbarSettingsMenu.mjs new file mode 100644 index 0000000..0c7fb9e --- /dev/null +++ b/module/apps/HotbarSettingsMenu.mjs @@ -0,0 +1,21 @@ +import { categories } from "../utils/SubMenuSettings.mjs"; +import { OFTSettingsMenu } from "./OFTSettingsMenu.mjs"; + +export class HotbarSettingsMenu extends OFTSettingsMenu { + static DEFAULT_OPTIONS = { + window: { + title: `OFT.menu.hotbarSettings.name`, + }, + }; + + static get _SETTINGS() { + const settings = categories.get(`hotbar`); + const settingIDs = []; + for (const [settingID, shown] of settings.entries()) { + if (shown) { + settingIDs.push(settingID); + }; + }; + return settingIDs; + }; +}; diff --git a/module/oft.mjs b/module/oft.mjs index 5765c9d..eec822e 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -17,6 +17,7 @@ import { DevSettingsMenu } from "./apps/DevSettingsMenu.mjs"; // Misc import { __ID__ } from "./consts.mjs"; +import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; Hooks.on(`setup`, () => { @@ -30,11 +31,19 @@ Hooks.on(`setup`, () => { addGlobalDocReferrer(); autoUnpauseOnLoad(); - chatSidebarBackground(); - startSidebarExpanded(); - startingSidebarTab(); + game.settings.registerMenu(__ID__, `hotbarSettings`, { + name: `OFT.menu.hotbarSettings.name`, + hint: `OFT.menu.hotbarSettings.hint`, + label: `OFT.menu.hotbarSettings.label`, + restricted: false, + type: HotbarSettingsMenu, + }); hotbarButtonSize(); hotbarButtonGap(); repositionHotbar(); + + chatSidebarBackground(); + startSidebarExpanded(); + startingSidebarTab(); preventUserConfigOpen(); }); diff --git a/module/settings/hotbarButtonGap.mjs b/module/settings/hotbarButtonGap.mjs index e381508..1ec2648 100644 --- a/module/settings/hotbarButtonGap.mjs +++ b/module/settings/hotbarButtonGap.mjs @@ -1,5 +1,6 @@ import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; +import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `hotbarButtonGap`; @@ -14,7 +15,7 @@ export function hotbarButtonGap() { // #region Registration Logger.log(`Registering setting: ${key}`); document.body.classList.add(`${__ID__}-${key}`); - game.settings.register(__ID__, key, { + registerCategorySetting(`hotbar`, __ID__, key, { name: `OFT.setting.${key}.name`, hint: `OFT.setting.${key}.hint`, scope: `user`, diff --git a/module/settings/hotbarButtonSize.mjs b/module/settings/hotbarButtonSize.mjs index 6bd1bba..c960c66 100644 --- a/module/settings/hotbarButtonSize.mjs +++ b/module/settings/hotbarButtonSize.mjs @@ -1,5 +1,6 @@ import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; +import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `hotbarButtonSize`; @@ -14,7 +15,7 @@ export function hotbarButtonSize() { // #region Registration Logger.log(`Registering setting: ${key}`); document.body.classList.add(`${__ID__}-${key}`); - game.settings.register(__ID__, key, { + registerCategorySetting(`hotbar`, __ID__, key, { name: `OFT.setting.${key}.name`, hint: `OFT.setting.${key}.hint`, scope: `user`, diff --git a/module/settings/repositionHotbar.mjs b/module/settings/repositionHotbar.mjs index 601e580..f85f3ed 100644 --- a/module/settings/repositionHotbar.mjs +++ b/module/settings/repositionHotbar.mjs @@ -1,5 +1,6 @@ import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; +import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `repositionHotbar`; @@ -13,7 +14,7 @@ export function repositionHotbar() { // #region Registration Logger.log(`Registering setting: ${key}`); - game.settings.register(__ID__, key, { + registerCategorySetting(`hotbar`, __ID__, key, { name: `OFT.setting.${key}.name`, hint: `OFT.setting.${key}.hint`, scope: `user`, From c946642873d1d41eb73c0d88cd1630983d0b7d33 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 19:59:47 -0700 Subject: [PATCH 03/13] Add spacing between settings in the submenus (closes #16) --- module/apps/OFTSettingsMenu.mjs | 3 ++- styles/apps.css | 8 ++++++++ styles/main.css | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 styles/apps.css diff --git a/module/apps/OFTSettingsMenu.mjs b/module/apps/OFTSettingsMenu.mjs index 1506c25..74ddf97 100644 --- a/module/apps/OFTSettingsMenu.mjs +++ b/module/apps/OFTSettingsMenu.mjs @@ -1,4 +1,4 @@ -import { filePath } from "../consts.mjs"; +import { __ID__, filePath } from "../consts.mjs"; const { HandlebarsApplicationMixin: HAM, ApplicationV2 } = foundry.applications.api; @@ -7,6 +7,7 @@ export class OFTSettingsMenu extends HAM(ApplicationV2) { // #region Options static DEFAULT_OPTIONS = { tag: `form`, + classes: [ __ID__ ], window: { icon: `fa-solid fa-gears`, resizable: true, diff --git a/styles/apps.css b/styles/apps.css new file mode 100644 index 0000000..5b2c628 --- /dev/null +++ b/styles/apps.css @@ -0,0 +1,8 @@ +.application.oft { + > .window-content.standard-form .setting-list { + flex-grow: 1; + display: flex; + flex-direction: column; + gap: 1rem; + } +} diff --git a/styles/main.css b/styles/main.css index 7c87f40..2312044 100644 --- a/styles/main.css +++ b/styles/main.css @@ -3,5 +3,7 @@ @import url("./hotbarButtonSize.css"); @import url("./repositionHotbar.css"); +@import url("./apps.css"); + /* Make the chat sidebar the same width as all the other tabs */ .chat-sidebar:not(.sidebar-popout) { width: unset; } From 2484f6a5981a0f76ebca5909c9925a0728f7e3dc Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 20:32:42 -0700 Subject: [PATCH 04/13] Make the startingSidebarTab fail gracefully when the tab isn't found (closes #17) --- module/settings/startingSidebarTab.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/settings/startingSidebarTab.mjs b/module/settings/startingSidebarTab.mjs index 94c6496..cc29f70 100644 --- a/module/settings/startingSidebarTab.mjs +++ b/module/settings/startingSidebarTab.mjs @@ -42,6 +42,10 @@ export function startingSidebarTab() { // #region Implementation Hooks.once(`ready`, () => { const defaultTab = game.settings.get(__ID__, key); + if (!(defaultTab in CONFIG.ui.sidebar.TABS)) { + Logger.error(`Failed to find starting tab with ID "${defaultTab}", skipping`); + return; + }; if (defaultTab) { Logger.debug(`Changing tab to:`, defaultTab); ui.sidebar.changeTab(defaultTab, `primary`); From baea567f241701897d55b312a57d41b70002bc69 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 20:59:46 -0700 Subject: [PATCH 05/13] Add setting to disable token auto-rotation (closes #12) --- langs/en-ca.json | 4 ++ module/oft.mjs | 4 +- module/settings/preventTokenRotation.mjs | 48 ++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 module/settings/preventTokenRotation.mjs diff --git a/langs/en-ca.json b/langs/en-ca.json index a182d15..4f5e0b6 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -21,6 +21,10 @@ "name": "Hotbar Button Size", "hint": "(v13+) Changes the size of the hotbar buttons to a size you prefer." }, + "preventTokenRotation": { + "name": "Prevent Token Auto-Rotation", + "hint": "(v13+, GM-Only) This prevents tokens from rotating while you are moving them allowing you to more easily use POG-style tokens without them being rotated automatically by Foundry." + }, "preventUserConfigOpen": { "name": "Prevent Auto User Config", "hint": "(v13+) Prevents Foundry from opening the User Configuration when a player loads into the world." diff --git a/module/oft.mjs b/module/oft.mjs index eec822e..53d3b77 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -7,6 +7,7 @@ import { autoUnpauseOnLoad } from "./settings/autoUnpauseOnLoad.mjs"; import { chatSidebarBackground } from "./settings/chatSidebarBackground.mjs"; import { hotbarButtonGap } from "./settings/hotbarButtonGap.mjs"; import { hotbarButtonSize } from "./settings/hotbarButtonSize.mjs"; +import { preventTokenRotation } from "./settings/preventTokenRotation.mjs"; import { preventUserConfigOpen } from "./settings/preventUserConfigOpen.mjs"; import { repositionHotbar } from "./settings/repositionHotbar.mjs"; import { startingSidebarTab } from "./settings/startingSidebarTab.mjs"; @@ -14,10 +15,10 @@ import { startSidebarExpanded } from "./settings/startSidebarExpanded.mjs"; // Apps import { DevSettingsMenu } from "./apps/DevSettingsMenu.mjs"; +import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; // Misc import { __ID__ } from "./consts.mjs"; -import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; Hooks.on(`setup`, () => { @@ -45,5 +46,6 @@ Hooks.on(`setup`, () => { chatSidebarBackground(); startSidebarExpanded(); startingSidebarTab(); + preventTokenRotation(); preventUserConfigOpen(); }); diff --git a/module/settings/preventTokenRotation.mjs b/module/settings/preventTokenRotation.mjs new file mode 100644 index 0000000..cff7ec5 --- /dev/null +++ b/module/settings/preventTokenRotation.mjs @@ -0,0 +1,48 @@ +import { __ID__ } from "../consts.mjs"; +import { Logger } from "../utils/Logger.mjs"; + +const key = `preventTokenRotation`; + +export function preventTokenRotation() { + + const prevented = Hooks.call(`${__ID__}.preventSetting`, key); + if (!prevented) { + Logger.log(`Preventing setting "${key}" from being registered`); + return; + }; + + /** @type {number|null} */ + let hookID = null; + + // #region Registration + Logger.log(`Registering setting: ${key}`); + game.settings.register(__ID__, key, { + name: `OFT.setting.${key}.name`, + hint: `OFT.setting.${key}.hint`, + scope: `world`, + type: Boolean, + default: true, + config: true, + requiresReload: false, + onChange: (newValue) => { + if (newValue) { + hookID = Hooks.on(`preMoveToken`, preMoveTokenHandler); + } else if (hookID != null) { + Hooks.off(`preMoveToken`, hookID); + }; + }, + }); + // #endregion Registration + + // #region Implementation + if (game.settings.get(__ID__, key)) { + hookID = Hooks.on(`preMoveToken`, preMoveTokenHandler); + }; + // #endregion Implementation +}; + +// #region Helpers +function preMoveTokenHandler(_token, update) { + update.autoRotate = false; +}; +// #endregion Helpers From dacb2e3046aa28cda97e4b9a35ff48a193658970 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 21:00:23 -0700 Subject: [PATCH 06/13] Make the graceful failure a bit more graceful --- module/settings/startingSidebarTab.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/settings/startingSidebarTab.mjs b/module/settings/startingSidebarTab.mjs index cc29f70..b512164 100644 --- a/module/settings/startingSidebarTab.mjs +++ b/module/settings/startingSidebarTab.mjs @@ -42,10 +42,13 @@ export function startingSidebarTab() { // #region Implementation Hooks.once(`ready`, () => { const defaultTab = game.settings.get(__ID__, key); + if (defaultTab === ``) { return }; + if (!(defaultTab in CONFIG.ui.sidebar.TABS)) { Logger.error(`Failed to find starting tab with ID "${defaultTab}", skipping`); return; }; + if (defaultTab) { Logger.debug(`Changing tab to:`, defaultTab); ui.sidebar.changeTab(defaultTab, `primary`); From b3119f5287ee91016f996df50f8e3b90c4e72e25 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 21:30:47 -0700 Subject: [PATCH 07/13] Hide the preventUserConfigOpen setting from GMs (closes #19) --- langs/en-ca.json | 2 +- module/settings/preventUserConfigOpen.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/langs/en-ca.json b/langs/en-ca.json index 4f5e0b6..9039cb5 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -27,7 +27,7 @@ }, "preventUserConfigOpen": { "name": "Prevent Auto User Config", - "hint": "(v13+) Prevents Foundry from opening the User Configuration when a player loads into the world." + "hint": "(v13+, Non-GMs) Prevents Foundry from opening the User Configuration when a player loads into the world." }, "repositionHotbar": { "name": "Reposition Hotbar", diff --git a/module/settings/preventUserConfigOpen.mjs b/module/settings/preventUserConfigOpen.mjs index 6377228..5833bb2 100644 --- a/module/settings/preventUserConfigOpen.mjs +++ b/module/settings/preventUserConfigOpen.mjs @@ -19,7 +19,7 @@ export function preventUserConfigOpen() { scope: `user`, type: Boolean, default: false, - config: true, + config: !game.user.isGM, requiresReload: false, }); // #endregion Registration From dfcbef81ef2323aee450a3848eb1db410c571e07 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 21:54:29 -0700 Subject: [PATCH 08/13] Added setting registration status (closes #20) --- dev/dev.mjs | 2 ++ dev/hooks/ready.mjs | 5 ++++ module.json | 3 ++- module/hooks/oft.preventSetting.mjs | 5 ++-- module/hooks/oft.settingStatuses.mjs | 13 +++++++++++ module/oft.mjs | 28 +++++++++++++++-------- module/settings/addGlobalDocReferrer.mjs | 1 + module/settings/autoUnpauseOnLoad.mjs | 4 +++- module/settings/chatSidebarBackground.mjs | 2 ++ module/settings/hotbarButtonGap.mjs | 4 +++- module/settings/hotbarButtonSize.mjs | 4 +++- module/settings/preventTokenRotation.mjs | 4 +++- module/settings/preventUserConfigOpen.mjs | 4 +++- module/settings/repositionHotbar.mjs | 4 +++- module/settings/startSidebarExpanded.mjs | 2 ++ module/settings/startingSidebarTab.mjs | 2 ++ 16 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 dev/dev.mjs create mode 100644 dev/hooks/ready.mjs create mode 100644 module/hooks/oft.settingStatuses.mjs diff --git a/dev/dev.mjs b/dev/dev.mjs new file mode 100644 index 0000000..ccb796e --- /dev/null +++ b/dev/dev.mjs @@ -0,0 +1,2 @@ +// Hooks +import "./hooks/ready.mjs"; diff --git a/dev/hooks/ready.mjs b/dev/hooks/ready.mjs new file mode 100644 index 0000000..ce55a53 --- /dev/null +++ b/dev/hooks/ready.mjs @@ -0,0 +1,5 @@ +import { __ID__ } from "../../module/consts.mjs"; + +Hooks.on(`ready`, () => { + console.table(game.modules.get(__ID__).api.registered); +}); diff --git a/module.json b/module.json index 86fedc1..cd9209b 100644 --- a/module.json +++ b/module.json @@ -14,7 +14,8 @@ "maximum": 13 }, "esmodules": [ - "module/oft.mjs" + "module/oft.mjs", + "dev/dev.mjs" ], "styles": [ { diff --git a/module/hooks/oft.preventSetting.mjs b/module/hooks/oft.preventSetting.mjs index 31026ac..500dc8e 100644 --- a/module/hooks/oft.preventSetting.mjs +++ b/module/hooks/oft.preventSetting.mjs @@ -5,7 +5,8 @@ of incompatabilities for whatever reason. This can also be used internally within this module if we discover incompatabilites with systems and want to disable it on our side. -This file is more as documentation than anything at this point in time. +This file is meant more documentation than anything at this point in +time. -Call Signature: (settingKey: string) => {} +Call Signature: (settingKey: string) => (void | boolean) */ diff --git a/module/hooks/oft.settingStatuses.mjs b/module/hooks/oft.settingStatuses.mjs new file mode 100644 index 0000000..46bef18 --- /dev/null +++ b/module/hooks/oft.settingStatuses.mjs @@ -0,0 +1,13 @@ +/* +This hook is used to enable any modules that attempt to disable settings +or just want to investigate what settings are enabled to be able to get +a ping with information about which settings where registered entirely +and which weren't. The object that is passed to this is frozen and is +not meant to be edited as you cannot de-register nor prevent setting +registration from this hook. For that see the "oft.preventSetting" hook. + +This file is meant more documentation than anything at this point in +time. + +Call Signature: (settings: Record) => void +*/ diff --git a/module/oft.mjs b/module/oft.mjs index 53d3b77..a54bfc2 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -20,6 +20,9 @@ import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; // Misc import { __ID__ } from "./consts.mjs"; +const { deepFreeze } = foundry.utils; +const status = {}; + Hooks.on(`setup`, () => { game.settings.registerMenu(__ID__, `devSettings`, { @@ -29,8 +32,8 @@ Hooks.on(`setup`, () => { restricted: false, type: DevSettingsMenu, }); - addGlobalDocReferrer(); - autoUnpauseOnLoad(); + status.addGlobalDocReferrer = addGlobalDocReferrer(); + status.autoUnpauseOnLoad = autoUnpauseOnLoad(); game.settings.registerMenu(__ID__, `hotbarSettings`, { name: `OFT.menu.hotbarSettings.name`, @@ -39,13 +42,18 @@ Hooks.on(`setup`, () => { restricted: false, type: HotbarSettingsMenu, }); - hotbarButtonSize(); - hotbarButtonGap(); - repositionHotbar(); + status.hotbarButtonSize = hotbarButtonSize(); + status.hotbarButtonGap = hotbarButtonGap(); + status.repositionHotbar = repositionHotbar(); - chatSidebarBackground(); - startSidebarExpanded(); - startingSidebarTab(); - preventTokenRotation(); - preventUserConfigOpen(); + status.chatSidebarBackground = chatSidebarBackground(); + status.startSidebarExpanded = startSidebarExpanded(); + status.startingSidebarTab = startingSidebarTab(); + status.preventTokenRotation = preventTokenRotation(); + status.preventUserConfigOpen = preventUserConfigOpen(); + + Hooks.callAll(`oft.settingStatuses`, deepFreeze(status)); + game.modules.get(__ID__).api = deepFreeze({ + registered: status, + }); }); diff --git a/module/settings/addGlobalDocReferrer.mjs b/module/settings/addGlobalDocReferrer.mjs index d40b1eb..735eebc 100644 --- a/module/settings/addGlobalDocReferrer.mjs +++ b/module/settings/addGlobalDocReferrer.mjs @@ -33,4 +33,5 @@ export function addGlobalDocReferrer() { }); // #endregion Implementation + return true; }; diff --git a/module/settings/autoUnpauseOnLoad.mjs b/module/settings/autoUnpauseOnLoad.mjs index 9bf84b3..de8e2c7 100644 --- a/module/settings/autoUnpauseOnLoad.mjs +++ b/module/settings/autoUnpauseOnLoad.mjs @@ -9,7 +9,7 @@ export function autoUnpauseOnLoad() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; // #region Registration @@ -34,4 +34,6 @@ export function autoUnpauseOnLoad() { }; }); // #endregion Implementation + + return true; }; diff --git a/module/settings/chatSidebarBackground.mjs b/module/settings/chatSidebarBackground.mjs index 6fab03d..c9728e2 100644 --- a/module/settings/chatSidebarBackground.mjs +++ b/module/settings/chatSidebarBackground.mjs @@ -28,4 +28,6 @@ export function chatSidebarBackground() { document.body.classList.add(`${__ID__}-${key}`); }; // #endregion Implementation + + return true; }; diff --git a/module/settings/hotbarButtonGap.mjs b/module/settings/hotbarButtonGap.mjs index 1ec2648..35edd13 100644 --- a/module/settings/hotbarButtonGap.mjs +++ b/module/settings/hotbarButtonGap.mjs @@ -9,7 +9,7 @@ export function hotbarButtonGap() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; // #region Registration @@ -37,4 +37,6 @@ export function hotbarButtonGap() { const buttonGap = game.settings.get(__ID__, key); document.body.style.setProperty(`--hotbar-button-gap`, `${buttonGap}px`); // #endregion Implementation + + return true; }; diff --git a/module/settings/hotbarButtonSize.mjs b/module/settings/hotbarButtonSize.mjs index c960c66..53d61d5 100644 --- a/module/settings/hotbarButtonSize.mjs +++ b/module/settings/hotbarButtonSize.mjs @@ -9,7 +9,7 @@ export function hotbarButtonSize() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; // #region Registration @@ -37,4 +37,6 @@ export function hotbarButtonSize() { const hotbarSize = game.settings.get(__ID__, key); document.body.style.setProperty(`--hotbar-size`, `${hotbarSize}px`); // #endregion Implementation + + return true; }; diff --git a/module/settings/preventTokenRotation.mjs b/module/settings/preventTokenRotation.mjs index cff7ec5..8224b9f 100644 --- a/module/settings/preventTokenRotation.mjs +++ b/module/settings/preventTokenRotation.mjs @@ -8,7 +8,7 @@ export function preventTokenRotation() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; /** @type {number|null} */ @@ -39,6 +39,8 @@ export function preventTokenRotation() { hookID = Hooks.on(`preMoveToken`, preMoveTokenHandler); }; // #endregion Implementation + + return true; }; // #region Helpers diff --git a/module/settings/preventUserConfigOpen.mjs b/module/settings/preventUserConfigOpen.mjs index 5833bb2..9069b7e 100644 --- a/module/settings/preventUserConfigOpen.mjs +++ b/module/settings/preventUserConfigOpen.mjs @@ -8,7 +8,7 @@ export function preventUserConfigOpen() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; // #region Registration @@ -32,4 +32,6 @@ export function preventUserConfigOpen() { }; }); // #endregion Implementation + + return true; }; diff --git a/module/settings/repositionHotbar.mjs b/module/settings/repositionHotbar.mjs index f85f3ed..6da7621 100644 --- a/module/settings/repositionHotbar.mjs +++ b/module/settings/repositionHotbar.mjs @@ -9,7 +9,7 @@ export function repositionHotbar() { const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return; + return false; }; // #region Registration @@ -43,4 +43,6 @@ export function repositionHotbar() { uiPosition.insertAdjacentElement(`beforeend`, container); }; // #endregion Implementation + + return true; }; diff --git a/module/settings/startSidebarExpanded.mjs b/module/settings/startSidebarExpanded.mjs index 0e76033..455dbcc 100644 --- a/module/settings/startSidebarExpanded.mjs +++ b/module/settings/startSidebarExpanded.mjs @@ -26,4 +26,6 @@ export function startSidebarExpanded() { }; }); // #endregion Implementation + + return true; }; diff --git a/module/settings/startingSidebarTab.mjs b/module/settings/startingSidebarTab.mjs index b512164..27d71d6 100644 --- a/module/settings/startingSidebarTab.mjs +++ b/module/settings/startingSidebarTab.mjs @@ -55,4 +55,6 @@ export function startingSidebarTab() { }; }); // #endregion Implementation + + return true; }; From 18021a32e40e9f2f8db630322578d7394e1b907e Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 9 Dec 2025 22:20:14 -0700 Subject: [PATCH 09/13] Version bump the manifest --- module.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.json b/module.json index cd9209b..61d9791 100644 --- a/module.json +++ b/module.json @@ -1,7 +1,7 @@ { "id": "oft", "title": "Oliver's Foundry Tweaks", - "version": "1.0.0", + "version": "1.1.0", "authors": [ { "name": "Oliver" } ], From 2a55ff522e8da72fc6bf389105c07a6e2f0f6898 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 13 Dec 2025 01:35:27 -0700 Subject: [PATCH 10/13] Add a way to auto-convert images in the chat into the img HTML tag --- module/oft.mjs | 2 + module/settings/chatImageLinks.mjs | 121 +++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 module/settings/chatImageLinks.mjs diff --git a/module/oft.mjs b/module/oft.mjs index a54bfc2..a3b5d5a 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -19,6 +19,7 @@ import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; // Misc import { __ID__ } from "./consts.mjs"; +import { chatImageLinks } from "./settings/chatImageLinks.mjs"; const { deepFreeze } = foundry.utils; const status = {}; @@ -46,6 +47,7 @@ Hooks.on(`setup`, () => { status.hotbarButtonGap = hotbarButtonGap(); status.repositionHotbar = repositionHotbar(); + status.chatImageLinks = chatImageLinks(); status.chatSidebarBackground = chatSidebarBackground(); status.startSidebarExpanded = startSidebarExpanded(); status.startingSidebarTab = startingSidebarTab(); diff --git a/module/settings/chatImageLinks.mjs b/module/settings/chatImageLinks.mjs new file mode 100644 index 0000000..77e06e2 --- /dev/null +++ b/module/settings/chatImageLinks.mjs @@ -0,0 +1,121 @@ +import { __ID__ } from "../consts.mjs"; +import { Logger } from "../utils/Logger.mjs"; + +const { DialogV2 } = foundry.applications.api; + +const key = `chatImageLinks`; +const IMAGE_TYPES = [ + `png`, + `jpg`, + `jpeg`, + `webp`, + `svg`, +]; + +export function chatImageLinks() { + + // #region Registration + Logger.log(`Registering setting: ${key}`); + game.settings.register(__ID__, key, { + name: `OFT.setting.${key}.name`, + hint: `OFT.setting.${key}.hint`, + scope: `user`, + type: Boolean, + default: true, + config: true, + requiresReload: true, + }); + + game.settings.register(__ID__, key + `-showPromptAgain`, { + scope: `user`, + type: Boolean, + default: true, + config: false, + }); + // #endregion Registration + + // #region Implementation + if (game.settings.get(__ID__, key)) { + Logger.log(`setting:${key} | Adding text enricher`); + + // MARK: Enricher + const pattern = new RegExp( + `(? { + Logger.debug(url); + url = url[0].replace(/^image:\/\//, ``); + const secure = `https://${url}`; + const insecure = `http://${url}`; + + if (await isAcceptableImage(secure)) { + const img = document.createElement(`img`); + img.src = secure; + img.alt = secure; + return img; + }; + + if (await isAcceptableImage(insecure)) { + const img = document.createElement(`img`); + img.src = insecure; + img.alt = insecure; + return img; + }; + + return null; + }, + }); + + // MARK: Chat Input + // Hooks.on(`chatMessage`, (chatLog, message, options) => { + // if (!game.settings.get(__ID__, key)) { return }; + + // const match = message.match(pattern); + // if (!match) { return }; + + // DialogV2.wait({ + // rejectClose: false, + // content: game.i18n.localize(`OFT.dialogs.chatImageLinks.didYouKnowImageLink`), + // buttons: [ + // { action: ``, label: `OFT.dialogs.chatImageLinks.convertAndDontShowAgain` }, + // { action: ``, label: `OFT.dialogs.chatImageLinks.justConvert` }, + // { action: ``, label: `OFT.dialogs.chatImageLinks.ignoreAndDontShowAgain` }, + // { action: ``, label: `OFT.dialogs.chatImageLinks.disableEntirely` }, + // ], + // }) + // .then((selected) => { + // chatLog.processMessage(message, options); + // }); + + // return false; + // }); + } + // #endregion Implementation + + return true; +}; + +// #region Helpers +async function isAcceptableImage(url) { + try { + const response = await fetch(url, { method: `HEAD` }); + const contentType = response.headers.get(`Content-Type`); + Logger.debug(`Image data:`, { url, contentType }); + let [ superType, subtype ] = contentType.split(`/`); + if (superType !== `image`) { + return false; + }; + if (subtype.includes(`+`)) { + subtype = subtype.split(`+`, 2).at(0); + }; + return IMAGE_TYPES.includes(subtype); + } catch { + return false; + }; +}; +// #endregion Helpers From 9c3213ebac327d175c301e66747280dafd8ace6b Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 13 Dec 2025 01:42:38 -0700 Subject: [PATCH 11/13] Add localization strings for the chatImageLinks setting --- langs/en-ca.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/langs/en-ca.json b/langs/en-ca.json index 9039cb5..8d607b0 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -9,6 +9,10 @@ "name": "Auto Unpause On Load", "hint": "(v13+, GM-Only) Automatically unpauses the game when you load into the world. This will happen EVERY time you load into the world, including if you reload the website." }, + "chatImageLinks": { + "name": "Image Shortcuts", + "hint": "When attempting to send an image/gif in chat, this allows you to easily embed the actual image in the text by changing \"http\"/\"https\" into \"image\", automatically displaying the image after sending the message." + }, "chatSidebarBackground": { "name": "Chat Background", "hint": "(v13+) Adds a background to the chat tab of the right-hand sidebar." @@ -60,6 +64,15 @@ "apps": { "no-settings-to-display": "No settings to display", "make-global-reference": "Make Global Reference" + }, + "dialogs": { + "chatImageLinks": { + "didYouKnowImageLink": "", + "convertAndDontShowAgain": "", + "justConvert": "", + "ignoreAndDontShowAgain": "", + "disableEntirely": "" + } } } } From 344e9c55ab080bc815a47a79149bcd9a5630ce2f Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 13 Dec 2025 01:42:59 -0700 Subject: [PATCH 12/13] Add preventSetting hook call for the chatImageLinks setting --- module/settings/chatImageLinks.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/settings/chatImageLinks.mjs b/module/settings/chatImageLinks.mjs index 77e06e2..1c7e3e6 100644 --- a/module/settings/chatImageLinks.mjs +++ b/module/settings/chatImageLinks.mjs @@ -14,6 +14,12 @@ const IMAGE_TYPES = [ export function chatImageLinks() { + const prevented = Hooks.call(`${__ID__}.preventSetting`, key); + if (!prevented) { + Logger.log(`Preventing setting "${key}" from being registered`); + return false; + }; + // #region Registration Logger.log(`Registering setting: ${key}`); game.settings.register(__ID__, key, { From c2601ba69ced71d908d0ace2244b5c06b3ef0fed Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 13 Dec 2025 21:31:56 -0700 Subject: [PATCH 13/13] Add better status indicators, and a setting to prevent movement history recording --- dev/hooks/ready.mjs | 2 +- langs/en-ca.json | 6 ++- module/hooks/init.mjs | 17 ++++++ module/hooks/setup.mjs | 58 ++++++++++++++++++++ module/oft.mjs | 61 +--------------------- module/settings/addGlobalDocReferrer.mjs | 4 +- module/settings/autoUnpauseOnLoad.mjs | 7 ++- module/settings/chatImageLinks.mjs | 7 ++- module/settings/chatSidebarBackground.mjs | 4 +- module/settings/hotbarButtonGap.mjs | 7 ++- module/settings/hotbarButtonSize.mjs | 7 ++- module/settings/preventMovementHistory.mjs | 42 +++++++++++++++ module/settings/preventTokenRotation.mjs | 7 ++- module/settings/preventUserConfigOpen.mjs | 7 ++- module/settings/repositionHotbar.mjs | 7 ++- module/settings/startSidebarExpanded.mjs | 4 +- module/settings/startingSidebarTab.mjs | 4 +- module/utils/SettingStatus.mjs | 11 ++++ 18 files changed, 183 insertions(+), 79 deletions(-) create mode 100644 module/hooks/init.mjs create mode 100644 module/hooks/setup.mjs create mode 100644 module/settings/preventMovementHistory.mjs create mode 100644 module/utils/SettingStatus.mjs diff --git a/dev/hooks/ready.mjs b/dev/hooks/ready.mjs index ce55a53..d7bea64 100644 --- a/dev/hooks/ready.mjs +++ b/dev/hooks/ready.mjs @@ -1,5 +1,5 @@ import { __ID__ } from "../../module/consts.mjs"; Hooks.on(`ready`, () => { - console.table(game.modules.get(__ID__).api.registered); + console.table(game.modules.get(__ID__).api.settings); }); diff --git a/langs/en-ca.json b/langs/en-ca.json index 8d607b0..02cd095 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -11,7 +11,7 @@ }, "chatImageLinks": { "name": "Image Shortcuts", - "hint": "When attempting to send an image/gif in chat, this allows you to easily embed the actual image in the text by changing \"http\"/\"https\" into \"image\", automatically displaying the image after sending the message." + "hint": "(v13+) When attempting to send an image/gif in chat, this allows you to easily embed the actual image in the text by changing \"http\"/\"https\" into \"image\", automatically displaying the image after sending the message." }, "chatSidebarBackground": { "name": "Chat Background", @@ -25,6 +25,10 @@ "name": "Hotbar Button Size", "hint": "(v13+) Changes the size of the hotbar buttons to a size you prefer." }, + "preventMovementHistory": { + "name": "Prevent Movement History", + "hint": "(v13+, GM-Only) This prevents Foundry from recording movement history of a token, but not disabling the movement ruler." + }, "preventTokenRotation": { "name": "Prevent Token Auto-Rotation", "hint": "(v13+, GM-Only) This prevents tokens from rotating while you are moving them allowing you to more easily use POG-style tokens without them being rotated automatically by Foundry." diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs new file mode 100644 index 0000000..60cde1b --- /dev/null +++ b/module/hooks/init.mjs @@ -0,0 +1,17 @@ +// Settings +import { preventMovementHistory } from "../settings/preventMovementHistory.mjs"; + +// Utils +import { Logger } from "../utils/Logger.mjs"; + +/* +This is only here for setting that **require** being registered during +initialization due to documentClass changes. If there is any way that +these settings can be implemented to work during the setup hook, that is +where they ideally should be implemented. +*/ +Hooks.on(`init`, () => { + Logger.log(`Initializing`); + + preventMovementHistory(); +}); diff --git a/module/hooks/setup.mjs b/module/hooks/setup.mjs new file mode 100644 index 0000000..ae63ec6 --- /dev/null +++ b/module/hooks/setup.mjs @@ -0,0 +1,58 @@ +// Settings +import { addGlobalDocReferrer } from "../settings/addGlobalDocReferrer.mjs"; +import { autoUnpauseOnLoad } from "../settings/autoUnpauseOnLoad.mjs"; +import { chatImageLinks } from "../settings/chatImageLinks.mjs"; +import { chatSidebarBackground } from "../settings/chatSidebarBackground.mjs"; +import { hotbarButtonGap } from "../settings/hotbarButtonGap.mjs"; +import { hotbarButtonSize } from "../settings/hotbarButtonSize.mjs"; +import { preventTokenRotation } from "../settings/preventTokenRotation.mjs"; +import { preventUserConfigOpen } from "../settings/preventUserConfigOpen.mjs"; +import { repositionHotbar } from "../settings/repositionHotbar.mjs"; +import { startingSidebarTab } from "../settings/startingSidebarTab.mjs"; +import { startSidebarExpanded } from "../settings/startSidebarExpanded.mjs"; + +// Apps +import { DevSettingsMenu } from "../apps/DevSettingsMenu.mjs"; +import { HotbarSettingsMenu } from "../apps/HotbarSettingsMenu.mjs"; + +// Misc +import { __ID__ } from "../consts.mjs"; +import { status } from "../utils/SettingStatus.mjs"; + +const { deepFreeze } = foundry.utils; + +Hooks.on(`setup`, () => { + + game.settings.registerMenu(__ID__, `devSettings`, { + name: `OFT.menu.devSettings.name`, + hint: `OFT.menu.devSettings.hint`, + label: `OFT.menu.devSettings.label`, + restricted: false, + type: DevSettingsMenu, + }); + addGlobalDocReferrer(); + autoUnpauseOnLoad(); + + game.settings.registerMenu(__ID__, `hotbarSettings`, { + name: `OFT.menu.hotbarSettings.name`, + hint: `OFT.menu.hotbarSettings.hint`, + label: `OFT.menu.hotbarSettings.label`, + restricted: false, + type: HotbarSettingsMenu, + }); + hotbarButtonSize(); + hotbarButtonGap(); + repositionHotbar(); + + chatImageLinks(); + chatSidebarBackground(); + startSidebarExpanded(); + startingSidebarTab(); + preventTokenRotation(); + preventUserConfigOpen(); + + Hooks.callAll(`oft.settingStatuses`, deepFreeze(status)); + game.modules.get(__ID__).api = deepFreeze({ + settings: status, + }); +}); diff --git a/module/oft.mjs b/module/oft.mjs index a3b5d5a..8740d00 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -1,61 +1,4 @@ // Hooks +import "./hooks/init.mjs"; +import "./hooks/setup.mjs"; import "./hooks/renderSettingsConfig.mjs"; - -// Settings -import { addGlobalDocReferrer } from "./settings/addGlobalDocReferrer.mjs"; -import { autoUnpauseOnLoad } from "./settings/autoUnpauseOnLoad.mjs"; -import { chatSidebarBackground } from "./settings/chatSidebarBackground.mjs"; -import { hotbarButtonGap } from "./settings/hotbarButtonGap.mjs"; -import { hotbarButtonSize } from "./settings/hotbarButtonSize.mjs"; -import { preventTokenRotation } from "./settings/preventTokenRotation.mjs"; -import { preventUserConfigOpen } from "./settings/preventUserConfigOpen.mjs"; -import { repositionHotbar } from "./settings/repositionHotbar.mjs"; -import { startingSidebarTab } from "./settings/startingSidebarTab.mjs"; -import { startSidebarExpanded } from "./settings/startSidebarExpanded.mjs"; - -// Apps -import { DevSettingsMenu } from "./apps/DevSettingsMenu.mjs"; -import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs"; - -// Misc -import { __ID__ } from "./consts.mjs"; -import { chatImageLinks } from "./settings/chatImageLinks.mjs"; - -const { deepFreeze } = foundry.utils; -const status = {}; - -Hooks.on(`setup`, () => { - - game.settings.registerMenu(__ID__, `devSettings`, { - name: `OFT.menu.devSettings.name`, - hint: `OFT.menu.devSettings.hint`, - label: `OFT.menu.devSettings.label`, - restricted: false, - type: DevSettingsMenu, - }); - status.addGlobalDocReferrer = addGlobalDocReferrer(); - status.autoUnpauseOnLoad = autoUnpauseOnLoad(); - - game.settings.registerMenu(__ID__, `hotbarSettings`, { - name: `OFT.menu.hotbarSettings.name`, - hint: `OFT.menu.hotbarSettings.hint`, - label: `OFT.menu.hotbarSettings.label`, - restricted: false, - type: HotbarSettingsMenu, - }); - status.hotbarButtonSize = hotbarButtonSize(); - status.hotbarButtonGap = hotbarButtonGap(); - status.repositionHotbar = repositionHotbar(); - - status.chatImageLinks = chatImageLinks(); - status.chatSidebarBackground = chatSidebarBackground(); - status.startSidebarExpanded = startSidebarExpanded(); - status.startingSidebarTab = startingSidebarTab(); - status.preventTokenRotation = preventTokenRotation(); - status.preventUserConfigOpen = preventUserConfigOpen(); - - Hooks.callAll(`oft.settingStatuses`, deepFreeze(status)); - game.modules.get(__ID__).api = deepFreeze({ - registered: status, - }); -}); diff --git a/module/settings/addGlobalDocReferrer.mjs b/module/settings/addGlobalDocReferrer.mjs index 735eebc..d955d40 100644 --- a/module/settings/addGlobalDocReferrer.mjs +++ b/module/settings/addGlobalDocReferrer.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; @@ -5,6 +6,7 @@ import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; const key = `addGlobalDocReferrer`; export function addGlobalDocReferrer() { + status[key] = SettingStatusEnum.Unknown; // #region Registration Logger.log(`Registering setting: ${key}`); @@ -33,5 +35,5 @@ export function addGlobalDocReferrer() { }); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/autoUnpauseOnLoad.mjs b/module/settings/autoUnpauseOnLoad.mjs index de8e2c7..de15fa4 100644 --- a/module/settings/autoUnpauseOnLoad.mjs +++ b/module/settings/autoUnpauseOnLoad.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; @@ -5,11 +6,13 @@ import { registerDevSetting } from "../utils/SubMenuSettings.mjs"; const key = `autoUnpauseOnLoad`; export function autoUnpauseOnLoad() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -35,5 +38,5 @@ export function autoUnpauseOnLoad() { }); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/chatImageLinks.mjs b/module/settings/chatImageLinks.mjs index 1c7e3e6..c25d56f 100644 --- a/module/settings/chatImageLinks.mjs +++ b/module/settings/chatImageLinks.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; @@ -13,11 +14,13 @@ const IMAGE_TYPES = [ ]; export function chatImageLinks() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -103,7 +106,7 @@ export function chatImageLinks() { } // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; // #region Helpers diff --git a/module/settings/chatSidebarBackground.mjs b/module/settings/chatSidebarBackground.mjs index c9728e2..5fce77a 100644 --- a/module/settings/chatSidebarBackground.mjs +++ b/module/settings/chatSidebarBackground.mjs @@ -1,9 +1,11 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; const key = `chatSidebarBackground`; export function chatSidebarBackground() { + status[key] = SettingStatusEnum.Unknown; // #region Registration Logger.log(`Registering setting: ${key}`); @@ -29,5 +31,5 @@ export function chatSidebarBackground() { }; // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/hotbarButtonGap.mjs b/module/settings/hotbarButtonGap.mjs index 35edd13..98c7cbf 100644 --- a/module/settings/hotbarButtonGap.mjs +++ b/module/settings/hotbarButtonGap.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; @@ -5,11 +6,13 @@ import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `hotbarButtonGap`; export function hotbarButtonGap() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -38,5 +41,5 @@ export function hotbarButtonGap() { document.body.style.setProperty(`--hotbar-button-gap`, `${buttonGap}px`); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/hotbarButtonSize.mjs b/module/settings/hotbarButtonSize.mjs index 53d61d5..7b4797b 100644 --- a/module/settings/hotbarButtonSize.mjs +++ b/module/settings/hotbarButtonSize.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; @@ -5,11 +6,13 @@ import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `hotbarButtonSize`; export function hotbarButtonSize() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -38,5 +41,5 @@ export function hotbarButtonSize() { document.body.style.setProperty(`--hotbar-size`, `${hotbarSize}px`); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/preventMovementHistory.mjs b/module/settings/preventMovementHistory.mjs new file mode 100644 index 0000000..8f4d18c --- /dev/null +++ b/module/settings/preventMovementHistory.mjs @@ -0,0 +1,42 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; +import { __ID__ } from "../consts.mjs"; +import { Logger } from "../utils/Logger.mjs"; + +const key = `preventMovementHistory`; + +export function preventMovementHistory() { + status[key] = SettingStatusEnum.Unknown; + + const prevented = Hooks.call(`${__ID__}.preventSetting`, key); + if (!prevented) { + Logger.log(`Preventing setting "${key}" from being registered`); + status[key] = SettingStatusEnum.Blocked; + return; + }; + + // #region Registration + Logger.log(`Registering setting: ${key}`); + game.settings.register(__ID__, key, { + name: `OFT.setting.${key}.name`, + hint: `OFT.setting.${key}.hint`, + scope: `world`, + type: Boolean, + default: false, + config: true, + reloadRequired: true, + }); + // #endregion Registration + + // #region Implementation + if (game.settings.get(__ID__, key)) { + class OFTTokenDocument extends CONFIG.Token.documentClass { + _shouldRecordMovementHistory() { + return false; + }; + }; + CONFIG.Token.documentClass = OFTTokenDocument; + }; + // #endregion Implementation + + status[key] = SettingStatusEnum.Registered; +}; diff --git a/module/settings/preventTokenRotation.mjs b/module/settings/preventTokenRotation.mjs index 8224b9f..258920c 100644 --- a/module/settings/preventTokenRotation.mjs +++ b/module/settings/preventTokenRotation.mjs @@ -1,14 +1,17 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; const key = `preventTokenRotation`; export function preventTokenRotation() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; /** @type {number|null} */ @@ -40,7 +43,7 @@ export function preventTokenRotation() { }; // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; // #region Helpers diff --git a/module/settings/preventUserConfigOpen.mjs b/module/settings/preventUserConfigOpen.mjs index 9069b7e..3b7646d 100644 --- a/module/settings/preventUserConfigOpen.mjs +++ b/module/settings/preventUserConfigOpen.mjs @@ -1,14 +1,17 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; const key = `preventUserConfigOpen`; export function preventUserConfigOpen() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -33,5 +36,5 @@ export function preventUserConfigOpen() { }); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/repositionHotbar.mjs b/module/settings/repositionHotbar.mjs index 6da7621..cce0c5f 100644 --- a/module/settings/repositionHotbar.mjs +++ b/module/settings/repositionHotbar.mjs @@ -1,3 +1,4 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; @@ -5,11 +6,13 @@ import { registerCategorySetting } from "../utils/SubMenuSettings.mjs"; const key = `repositionHotbar`; export function repositionHotbar() { + status[key] = SettingStatusEnum.Unknown; const prevented = Hooks.call(`${__ID__}.preventSetting`, key); if (!prevented) { Logger.log(`Preventing setting "${key}" from being registered`); - return false; + status[key] = SettingStatusEnum.Blocked; + return; }; // #region Registration @@ -44,5 +47,5 @@ export function repositionHotbar() { }; // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/startSidebarExpanded.mjs b/module/settings/startSidebarExpanded.mjs index 455dbcc..4cf9f2d 100644 --- a/module/settings/startSidebarExpanded.mjs +++ b/module/settings/startSidebarExpanded.mjs @@ -1,9 +1,11 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; const key = `startSidebarExpanded`; export function startSidebarExpanded() { + status[key] = SettingStatusEnum.Unknown; // #region Registration Logger.log(`Registering setting: ${key}`); @@ -27,5 +29,5 @@ export function startSidebarExpanded() { }); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/settings/startingSidebarTab.mjs b/module/settings/startingSidebarTab.mjs index 27d71d6..02fab17 100644 --- a/module/settings/startingSidebarTab.mjs +++ b/module/settings/startingSidebarTab.mjs @@ -1,9 +1,11 @@ +import { SettingStatusEnum, status } from "../utils/SettingStatus.mjs"; import { __ID__ } from "../consts.mjs"; import { Logger } from "../utils/Logger.mjs"; const key = `startingSidebarTab`; export function startingSidebarTab() { + status[key] = SettingStatusEnum.Unknown; // #region Registration Logger.log(`Registering setting: ${key}`); @@ -56,5 +58,5 @@ export function startingSidebarTab() { }); // #endregion Implementation - return true; + status[key] = SettingStatusEnum.Registered; }; diff --git a/module/utils/SettingStatus.mjs b/module/utils/SettingStatus.mjs new file mode 100644 index 0000000..d3f1dd5 --- /dev/null +++ b/module/utils/SettingStatus.mjs @@ -0,0 +1,11 @@ +/** @typedef {typeof SettingStatusEnum[keyof typeof SettingStatusEnum]} SettingStatus */ + +export const SettingStatusEnum = foundry.utils.deepFreeze({ + Registered: `registered`, + Blocked: `blocked`, + Incompatible: `incompatible`, + Unknown: `unknown`, +}); + +/** @type {Record} */ +export const status = {};