All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

143 lines
5.3 KiB

class OwnershipViewer {
// Creates and applies the OwnershipViewer div to each document in a directory - called when each directory renders.
static directoryRendered(obj, html, data) {
if (!game.user.isGM || !obj._getEntryContextOptions) return;
// Get the current directory's right-click context options, then tore the ownership config option
const contextOptions = obj._getEntryContextOptions();
const ownershipOption = contextOptions.find((e) => e.name === "OWNERSHIP.Configure");
// Determine if we are working with a directory or a journal sheet
const isJournalSheet = obj.constructor.name === "JournalSheet";
// Gather all documents in the current directory or journal
const collection = isJournalSheet ? obj.object.collections.pages : obj.constructor.collection;
const documentList = html.find(`li.directory-item${isJournalSheet ? ".level1" : ".document"}`);
// Interate through each directory list item.
for (let li of documentList) {
// Match it to the corresponding document
li = $(li);
const document = collection.get(li.attr(`data-${isJournalSheet ? "page" : "document"}-id`));
const users = [];
// Iterate through each ownership definition on the document
for (let id in document.ownership) {
const ownership = document.ownership[id] ?? 0;
// If the ownership definition isn't 'None'...
if (ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
// Create the div for this ownership definition, with the appropriate class based on the ownership level
const user_div = $(`<div data-user-id=${id}></div>`);
// And if the ownership definition isn't 'All Players' (default) or a GM, set 'bg_color' to the user's color
const user = game.users.get(id);
if (id !== "default") {
if (user && !user.isGM) {
user_div.css({ "background-color": user.color });
user_div.attr("data-tooltip", user.name);
} else {
continue;
}
}
const ownerships = invertObject(CONST.DOCUMENT_OWNERSHIP_LEVELS);
user_div.addClass(`ownership-viewer-${ownerships[ownership].toLowerCase()}`);
user_div.attr(
"data-tooltip",
`${user ? user.name + ": " : ""} ${game.i18n.localize("OWNERSHIP." + ownerships[ownership])}`
);
user_div.attr("data-tooltip-direction", "UP");
if (id == "default") {
user_div.addClass("ownership-viewer-all");
} else {
user_div.addClass("ownership-viewer-user");
}
// Store the resulting div and keep iterating through the other ownership definitions on the document
users.push(user_div);
}
}
const div = $('<div class="ownership-viewer"></div>');
// Append the collection of divs to the document's list item, or add the 'none set' icon if empty
if (ownershipOption) {
if (users.length === 0) {
users.push($('<div><i class="fas fa-share-alt" style="color: white;"></i></div>'));
}
const anchor = $(`<a href="#"></a>`);
div.append(anchor);
anchor.append(...users);
} else {
div.append(...users);
}
if (isJournalSheet) {
li.find(".page-ownership").remove();
li.find(".page-heading").append(div);
} else {
li.append(div);
}
}
// Ensure any clicks on the OwnershipViewer div open the ownership config for that document
if (ownershipOption) {
function registerClickEvents() {
html.find(".ownership-viewer").click((event) => {
event.preventDefault();
event.stopPropagation();
const li = $(event.currentTarget).closest("li");
if (li) ownershipOption.callback(li);
});
}
if (isJournalSheet) {
// On journal sheets, delay registering click events until the page is selected and its header is expanded
Hooks.once("renderJournalPageSheet", () => {
registerClickEvents();
});
} else {
registerClickEvents();
}
}
}
// Update the user color in OwnershipViewer divs if the user is edited
static userUpdated(user) {
for (let user_div of $(".ownership-viewer-user")) {
let id = $(user_div).attr("data-user-id");
if (id == user.id) {
$(user_div).css("background-color", user.color);
}
}
}
// Makes the color assigned to each player clearer in the player list if they are inactive.
static playerListRendered(list, html, options) {
if (!options.showOffline) return;
const userIdColorMap = game.users.contents
.filter((user) => !user.active)
.reduce((map, user) => {
map[user.id] = user.color;
return map;
}, {});
const players = html[0].querySelectorAll("span.player-active.inactive");
for (let player of players) {
const id = player.parentElement.dataset.userId;
player.style.borderColor = userIdColorMap[id];
}
}
}
Hooks.on("renderJournalSheet", OwnershipViewer.directoryRendered);
Hooks.on("renderJournalDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderSceneDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderActorDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderItemDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderMacroDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderRollTableDirectory", OwnershipViewer.directoryRendered);
Hooks.on("renderCardsDirectory", OwnershipViewer.directoryRendered);
Hooks.on("updateUser", OwnershipViewer.userUpdated);
Hooks.on("renderPlayerList", OwnershipViewer.playerListRendered);