Add tweak to allow changing the right-sidebar tab order #46

Merged
Oliver merged 7 commits from feature/rearrange-sidebar-tabs into main 2026-02-27 06:06:42 +00:00
5 changed files with 99 additions and 9 deletions
Showing only changes of commit 8c8d16e315 - Show all commits

View file

@ -102,7 +102,12 @@
"SidebarTabRearranger": { "SidebarTabRearranger": {
"title": "Rearrange Sidebar Tabs", "title": "Rearrange Sidebar Tabs",
"top": "Top", "top": "Top",
"bottom": "Bottom" "bottom": "Bottom",
"save-user": "Save Changes for User",
"remove-user": "Remove User Order",
"save-world": "Save Changes for World",
"remove-world": "Remove World Order",
"user-override-warning": "You have a User-level tab order, saving any changes to the World-level tab order will not show up for you."
} }
}, },
"notifs": { "notifs": {

View file

@ -1,7 +1,9 @@
import { __ID__, filePath } from "../consts.mjs"; import { __ID__, filePath } from "../consts.mjs";
import { performArraySort } from "../utils/performArraySort.mjs"; import { performArraySort } from "../utils/performArraySort.mjs";
import { key as rearrangeSidebarTabsKey } from "../tweaks/rearrangeSidebarTabs.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const { SettingsConfig } = foundry.applications.settings;
const { DragDrop } = foundry.applications.ux; const { DragDrop } = foundry.applications.ux;
const { getDocumentClass } = foundry.utils; const { getDocumentClass } = foundry.utils;
@ -23,6 +25,7 @@ export class SidebarTabRearranger extends HandlebarsApplicationMixin(Application
submitOnChange: false, submitOnChange: false,
}, },
actions: { actions: {
unsetSetting: this.#unsetSetting,
}, },
}; };
@ -37,10 +40,16 @@ export class SidebarTabRearranger extends HandlebarsApplicationMixin(Application
constructor(...args) { constructor(...args) {
super(...args); super(...args);
// TODO: define this using the game settings
this.#order = Object.keys(ui.sidebar.constructor.TABS); this.#order = Object.keys(ui.sidebar.constructor.TABS);
}; };
get worldSave() {
return game.settings.get(__ID__, `${rearrangeSidebarTabsKey}World`);
};
get userSave() {
return game.settings.get(__ID__, `${rearrangeSidebarTabsKey}User`);
};
// #endregion Instance Data // #endregion Instance Data
// #region Lifecycle // #region Lifecycle
@ -61,7 +70,21 @@ export class SidebarTabRearranger extends HandlebarsApplicationMixin(Application
}; };
/** @this {SidebarTabRearranger} */ /** @this {SidebarTabRearranger} */
static async #onSubmit() {}; static async #onSubmit(event) {
const { scope } = event.submitter.dataset;
if (!scope || ![`User`, `World`].includes(scope)) { return };
if (scope === `World` && this.userSave != null) {
return;
}
game.settings.set(
__ID__,
`${rearrangeSidebarTabsKey}${scope}`,
this.#order,
);
SettingsConfig.reloadConfirm({ world: scope === `World` });
};
// #endregion Lifecycle // #endregion Lifecycle
// #region Data Prep // #region Data Prep
@ -69,7 +92,9 @@ export class SidebarTabRearranger extends HandlebarsApplicationMixin(Application
const ctx = { const ctx = {
meta: { meta: {
idp: this.id, idp: this.id,
isGM: game.user.isGM,
}, },
showUserOverrideWarning: game.user.isGM && this.userSave != null,
}; };
const tabs = ui.sidebar.constructor.TABS; const tabs = ui.sidebar.constructor.TABS;
@ -100,6 +125,14 @@ export class SidebarTabRearranger extends HandlebarsApplicationMixin(Application
// #endregion Data Prep // #endregion Data Prep
// #region Actions // #region Actions
/** @this {SidebarTabRearranger} */
static async #unsetSetting(event, target) {
const { scope } = target.dataset;
if (!scope || ![`User`, `World`].includes(scope)) { return };
await game.settings.set(__ID__, `${rearrangeSidebarTabsKey}${scope}`, null);
SettingsConfig.reloadConfirm({ world: scope === `World` });
};
// #endregion Actions // #endregion Actions
// #region Drag & Drop // #region Drag & Drop

View file

@ -3,10 +3,18 @@
gap: 16px; gap: 16px;
} }
main {
width: min-content;
}
footer { footer {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: 8px; gap: 8px;
.wide {
grid-column: span 2;
}
} }
.drop-zone { .drop-zone {
@ -66,4 +74,11 @@
.bottom-label { .bottom-label {
text-align: right; text-align: right;
} }
.warning {
border: 1px solid var(--color-level-warning-border);
border-radius: 4px;
padding: 4px 6px;
font-weight: 600;
}
} }

View file

@ -1,14 +1,46 @@
<footer> <footer>
<button type="close"> <button data-scope="User">
{{ localize "OFT.apps.discard-changes" }}
</button>
<button>
<oft-icon <oft-icon
name="icons/save" name="icons/save"
aria-hidden="true" aria-hidden="true"
var:fill="currentColor" var:fill="currentColor"
var:size="1rem" var:size="1rem"
></oft-icon> ></oft-icon>
{{ localize "Save Changes" }} {{ localize "OFT.apps.SidebarTabRearranger.save-user" }}
</button>
<button
type="button"
data-action="unsetSetting"
data-scope="User"
>
{{ localize "OFT.apps.SidebarTabRearranger.remove-user" }}
</button>
{{#if meta.isGM}}
<button
data-scope="World"
>
<oft-icon
name="icons/save"
aria-hidden="true"
var:fill="currentColor"
var:size="1rem"
></oft-icon>
{{ localize "OFT.apps.SidebarTabRearranger.save-world" }}
</button>
<button
type="button"
data-action="unsetSetting"
data-scope="World"
>
{{ localize "OFT.apps.SidebarTabRearranger.remove-world" }}
</button>
{{/if}}
<button
class="wide"
type="close"
>
{{ localize "OFT.apps.discard-changes" }}
</button> </button>
</footer> </footer>

View file

@ -1,4 +1,9 @@
<main> <main>
{{#if showUserOverrideWarning}}
<p class="warning">
{{ localize "OFT.apps.SidebarTabRearranger.user-override-warning" }}
</p>
{{/if}}
<div class="top-label"> <div class="top-label">
{{ localize "OFT.apps.SidebarTabRearranger.top" }} {{ localize "OFT.apps.SidebarTabRearranger.top" }}
</div> </div>