From ab0a7c21411d69eb0f925ee475025d62f7ad5759 Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Fri, 12 Mar 2021 12:17:08 +1000 Subject: [PATCH 1/3] Add player settings support --- .editorconfig | 15 +++ .gitignore | 1 + README.md | 19 +-- changelog.md | 7 ++ languages/en.json | 56 +++++++++ module.json | 44 ++++--- modules/init.js | 43 ------- scripts/config.js | 20 ++++ modules/FCE.js => scripts/core.js | 141 ++++++++++++++++------ scripts/module.js | 71 +++++++++++ scripts/player-settings.js | 188 ++++++++++++++++++++++++++++++ scripts/preloadTemplates.js | 10 ++ scripts/prompt.js | 154 ------------------------ styles/module.css | 13 +++ templates/player-settings.html | 91 +++++++++++++++ templates/world-settings.html | 35 ++++++ 16 files changed, 655 insertions(+), 253 deletions(-) create mode 100644 .editorconfig create mode 100644 languages/en.json delete mode 100644 modules/init.js create mode 100644 scripts/config.js rename modules/FCE.js => scripts/core.js (50%) create mode 100644 scripts/module.js create mode 100644 scripts/player-settings.js create mode 100644 scripts/preloadTemplates.js delete mode 100644 scripts/prompt.js create mode 100644 styles/module.css create mode 100644 templates/player-settings.html create mode 100644 templates/world-settings.html diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d8d7320 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# Top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 0dd20ab..956656c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules/ foundry.js package.json /changelog.html +.DS_Store diff --git a/README.md b/README.md index c31803e..58762a2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # FoundryVTT - Forien's Copy Environment -![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/forien/foundryvtt-forien-copy-environment?style=for-the-badge) -![GitHub Releases](https://img.shields.io/github/downloads/Forien/foundryvtt-forien-copy-environment/latest/total?style=for-the-badge) -![GitHub Releases](https://img.shields.io/github/downloads/Forien/foundryvtt-forien-copy-environment/total?style=for-the-badge) -**[Compatibility]**: *FoundryVTT* 0.6.0+ -**[Systems]**: *any* + +![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/League-of-Foundry-Developers/foundryvtt-forien-copy-environment) ![GitHub Releases](https://img.shields.io/github/downloads/League-of-Foundry-Developers/foundryvtt-forien-copy-environment/latest/total) ![GitHub Releases](https://img.shields.io/github/downloads/League-of-Foundry-Developers/foundryvtt-forien-copy-environment/total) ![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Fforien-copy-environment&colorB=4aa94a) + +**NOTE** This is an unofficial forked version of the module maintained by the League of Foundry Developers to provide module continuity while Forien is unavailable. + +**[Compatibility]**: *FoundryVTT* 0.7.0+ +**[Systems]**: *any* This module allows for fast copy/save environment data such as core version or list of installed modules and their versions. Supports copying as TXT or saving as JSON. @@ -11,7 +13,7 @@ Module also allows to export (save/backup) current game settings and then import ## Installation -1. Install Forien's Copy Environment using manifest URL: https://raw.githubusercontent.com/Forien/foundryvtt-forien-copy-environment/master/module.json +1. Install Forien's Copy Environment using manifest URL: https://raw.githubusercontent.com/League-of-Foundry-Developers/foundryvtt-forien-copy-environment/master/module.json 2. While loaded in World, enable **_Forien's Copy Environment_** module. ### Usage @@ -26,13 +28,14 @@ Go to Settings tab in Sidebar and **right click** on data **below** "General Inf * Save Environment (including manifest links) as a JSON file * Export game settings (both 'world' and 'client' scopes) * Import game settings ('client' ones, and if you are GM also 'world' ones) +* Export player settings (such as player color and "dice" settings) +* Import player settings (you will be able to choose which ones you want to import) *Please note that importing 'world' scope settings en masse as GM might cause some issues to connected players. I advise players should logout before attempt to import World Settings* ## Contact -If you wish to contact me for any reason, reach me out on Discord using my tag: `Forien#2130` - +[League of Foundry Developers](https://discord.gg/gzemMfHURH) ~~If you wish to contact me for any reason, reach me out on Discord using my tag: `Forien#2130`~~ ## Support diff --git a/changelog.md b/changelog.md index 5a3bf34..093b071 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,13 @@ # Changelog +### v2.0.0 + +* Migrated to [League of Foundry Developers](https://discord.gg/gzemMfHURH) +* Added Settings configuration in addition to the right-click context menu +* Added export/import of player settings including differential based selection + ### v1.1.1 + * Added 0.6.6 compatibility ## v1.1.0 diff --git a/languages/en.json b/languages/en.json new file mode 100644 index 0000000..6b7ac9a --- /dev/null +++ b/languages/en.json @@ -0,0 +1,56 @@ +{ + "forien-copy-environment": { + "settings": { + "player-settings": { + "Name": "Player Settings", + "Label": "Import / Export Player Settings", + "Hint": "Import and Export your player settings, based on player Names across worlds." + }, + "world": { + "Name": "World Settings", + "Label": "Import / Export World Settings", + "Hint": "Import and Export your world settings, including modules." + } + }, + "forms": { + "world": { + "title": "World Settings", + "environment": { + "tabTitle": "Environment", + "download": "Download", + "copy": "Copy to clipboard", + "copyIntro": "Copy environment to clipboard", + "intro": "Export world environment.", + "exportIntro": "Export environment.json", + "importIntro": "There is no import of the environment settings file as it is informational only. If you wish to import the modules you can do so by importing the World Settings." + }, + "settings": { + "tabTitle": "Settings", + "download": "Download", + "intro": "Export world settings, including which modules are enabled/disabled.", + "exportIntro": "Export settings.json", + "importIntro": "Import settings.json" + } + }, + "player-settings": { + "title": "Player Settings", + "import": { + "tabTitle": "Import", + "save": "Import player settings", + "playerList": "Import settings for the following players:", + "existing": "Import an existing Export:", + "property": "Property", + "newValue": "New Value", + "currentValue": "Current Value", + "notFound": "The following users in the import file do not exist in this world and will be skipped." + }, + "export": { + "tabTitle": "Export", + "save": "Export player settings", + "playerList": "Export settings for the following players:" + }, + "updateSuccess": "Updated player settings for: " + } + } + } +} diff --git a/module.json b/module.json index 26173c5..ea7a80b 100644 --- a/module.json +++ b/module.json @@ -1,26 +1,44 @@ { "name": "forien-copy-environment", "title": "Forien's Copy Environment", - "description": "Allows for copying TXT/JSON list of system/modules and versions, and gives ability to export/import game settings", + "description": "Allows for copying TXT/JSON list of system/modules and versions, and gives ability to export/import game and player settings", + "version": "2.0.0", + "library": "false", + "manifestPlusVersion": "1.0.0", + "minimumCoreVersion": "0.7.6", + "compatibleCoreVersion": "0.7.9", "author": "Forien — Forien#2130", "authors": [ { "name": "Forien", "url": "https://www.patreon.com/forien" + }, + { + "name": "The League of Extraordinary FVTT Developers", + "url": "https://github.com/League-of-Foundry-Developers" + }, + { + "name": "Blair McMillan", + "url": "https://github.com/sneat", + "discord": "blair#9056" } ], - "version": "1.1.1", - "minimumCoreVersion": "0.6.0", - "compatibleCoreVersion": "0.7.1", - "url": "https://github.com/Forien/foundryvtt-forien-copy-environment", - "manifest": "https://raw.githubusercontent.com/Forien/foundryvtt-forien-copy-environment/master/module.json", - "download": "https://github.com/Forien/foundryvtt-forien-copy-environment/releases/download/v1.1.1/v1.1.1.zip", - "readme": "https://github.com/Forien/foundryvtt-forien-copy-environment/blob/v1.1.1/README.md", - "bugs": "https://github.com/Forien/foundryvtt-forien-copy-environment/issues", "esmodules": [ - "./modules/init.js" + "/scripts/module.js" + ], + "styles": [ + "/styles/module.css" + ], + "languages": [ + { + "lang": "en", + "name": "English", + "path": "languages/en.json" + } ], - "scripts": [ - "./scripts/prompt.js" - ] + "url": "This is auto replaced", + "manifest": "This is auto replaced", + "download": "This is auto replaced", + "bugs": "https://github.com/League-of-Foundry-Developers/foundryvtt-forien-copy-environment/issues", + "allowBugReporter": true } diff --git a/modules/init.js b/modules/init.js deleted file mode 100644 index b53b2d6..0000000 --- a/modules/init.js +++ /dev/null @@ -1,43 +0,0 @@ -import FCE from "./FCE.js"; - -Hooks.on("renderSettings", function (app, html, data) { - if (game.user.isGM) { - new ContextMenu(html, "div.game-system, ul#game-details", [ - { - name: "Copy as text", - icon: '', - callback: li => { - FCE.copy(); - } - }, - { - name: "Save as JSON", - icon: '', - callback: li => { - FCE.save(); - } - }, - /*{ - name: "Advanced…", - icon: '', - callback: li => { - FCE.advanced(); - } - },*/ - { - name: "Export Settings", - icon: '', - callback: li => { - FCE.export(); - } - }, - { - name: "Import Settings", - icon: '', - callback: li => { - FCE.import(); - } - } - ]); - } -}); diff --git a/scripts/config.js b/scripts/config.js new file mode 100644 index 0000000..68f5f21 --- /dev/null +++ b/scripts/config.js @@ -0,0 +1,20 @@ +export const name = 'forien-copy-environment'; + +export const templates = { + playerSettings: `modules/${name}/templates/player-settings.html`, + worldSettings: `modules/${name}/templates/world-settings.html`, +}; + +export function log(force, ...args) { + try { + if (typeof force !== 'boolean') { + console.warn('Copy Environment | Invalid log usage. Expected "log(force, ...args)" as boolean but got', force); + } + + const isDebugging = window.DEV?.getPackageDebugValue(name); + + if (force || isDebugging) { + console.log('Copy Environment |', ...args); + } + } catch (e) {} +} diff --git a/modules/FCE.js b/scripts/core.js similarity index 50% rename from modules/FCE.js rename to scripts/core.js index f701623..0b4d446 100644 --- a/modules/FCE.js +++ b/scripts/core.js @@ -1,4 +1,82 @@ -export default class FCE { +import { + name, + templates, + log +} from './config.js' + +export default class Core extends FormApplication { + + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ['copy-environment-world-settings'], + height: 'auto', + width: 600, + id: `${name}-world-settings`, + title: `${name}.forms.world.title`, + template: templates.worldSettings, + tabs: [{ + navSelector: '.tabs', + contentSelector: 'form', + initial: 'settings', + }] + }); + } + + getData() { + return {}; + } + + + activateListeners(html) { + super.activateListeners(html); + + html.on('click', '.export-save-world-env', () => { + Core.saveSummaryAsJSON(); + this.close(); + }); + + html.on('click', '.export-copy-world-env', () => { + Core.copyAsText(); + this.close(); + }); + + html.on('click', '.export-save-world-settings', () => { + Core.exportGameSettings(); + this.close(); + }); + + html.on('change', '.import-world-settings', (el) => { + Core.importGameSettings(el.target); + this.close(); + }); + } + + static download(data, filename) { + if (!filename) { + log(false, 'Missing filename on download request'); + return; + } + + let jsonStr = JSON.stringify(data, null, 2); + + saveDataToFile(jsonStr, 'application/json', filename); + } + + static getData() { + let modules = game.data.modules.filter(m => m.active); + let system = game.data.system; + let core = game.data.version; + + let message = "List generated with Forien's Copy Environment: https://github.com/League-of-Foundry-Developers/foundryvtt-forien-copy-environment"; + + return { + message, + core, + system, + modules + }; + } + static getText() { let data = this.getData(); let text = `Core Version: ${data.core}\n\n`; @@ -12,10 +90,12 @@ export default class FCE { text += `\n${data.message}`; + log(false, text); + return text; } - static copy() { + static copyAsText() { let text = this.getText(); const el = document.createElement('textarea'); @@ -31,10 +111,12 @@ export default class FCE { ui.notifications.info("Environment data copied to clipboard!", {}); } - static save() { + static saveSummaryAsJSON() { let data = this.getData(); - data.core = {version: data.core}; + data.core = { + version: data.core + }; data.system = { id: data.system.id, version: data.system.data.version, @@ -53,33 +135,36 @@ export default class FCE { this.download(data, 'foundry-environment.json'); } - static download(data, filename = 'forien-copy-environment.json') { - let jsonStr = JSON.stringify(data, null, 2); - - saveDataToFile(jsonStr, 'application/json', filename); - } - - static export() { - let data = game.data.settings.map(s => ({key: s.key, value: s.value})); + static exportGameSettings() { + let data = game.data.settings.map(s => ({ + key: s.key, + value: s.value + })); this.download(data, 'foundry-settings-export.json'); } - static import() { + static importGameSettingsQuick() { const input = $(''); - input.on("change", this.importSettings); + input.on("change", () => Core.importGameSettings(input.get(0))); input.trigger('click'); } - static importSettings() { - const file = this.files[0]; - if (!file) return; + static importGameSettings(el) { + const file = el?.files[0]; + if (!file) { + log(false, 'No file provided for game settings importer.'); + return; + } readTextFromFile(file).then(async result => { const settings = JSON.parse(result); + log(false, 'import settings', settings); for (const setting of settings) { - await FCE.processSetting(setting); + await Core.processSetting(setting); } - location.reload(); + + ui.notifications.info("Updated world settings. Reloading world in 5sec...", {}); + window.setTimeout(window.location.reload.bind(window.location), 5000); }); } @@ -96,23 +181,9 @@ export default class FCE { data: setting }); } catch (e) { - console.log(`Setting key ${setting.key} could not be dispatched to server.`); + log(false, `Setting key ${setting.key} could not be dispatched to server.`); console.error(e); } } } - - static getData() { - let modules = this.getModules(); - let system = game.data.system; - let core = game.data.version; - - let message = "List generated with Forien's Copy Environment: https://github.com/Forien/foundryvtt-forien-copy-environment"; - - return {message, core, system, modules}; - } - - static getModules() { - return game.data.modules.filter(m => m.active); - } -} \ No newline at end of file +} diff --git a/scripts/module.js b/scripts/module.js new file mode 100644 index 0000000..335cdbc --- /dev/null +++ b/scripts/module.js @@ -0,0 +1,71 @@ +import { name } from './config.js'; +import Core from './core.js' +import CopyEnvironmentPlayerSettings from './player-settings.js'; + +Hooks.once('init', async function () { + +}); + +Hooks.once('ready', async function () { + game.settings.registerMenu(name, 'world-settings', { + name: `${name}.settings.world.Name`, + label: `${name}.settings.world.Label`, + icon: 'fas fa-cogs', + type: Core, + restricted: true, + hint: `${name}.settings.world.Hint`, + }); + game.settings.registerMenu(name, 'player-settings', { + name: `${name}.settings.player-settings.Name`, + label: `${name}.settings.player-settings.Label`, + icon: 'fas fa-cogs', + type: CopyEnvironmentPlayerSettings, + restricted: true, + hint: `${name}.settings.player-settings.Hint`, + }); +}); + +Hooks.once('devModeReady', ({ registerPackageDebugFlag }) => { + registerPackageDebugFlag(name); +}); + +Hooks.on("renderSettings", function (app, html, data) { + if (game.user.isGM) { + new ContextMenu(html, "div.game-system, ul#game-details", [{ + name: "Copy as text", + icon: '', + callback: () => { + Core.copyAsText(); + } + }, + { + name: "Save as JSON", + icon: '', + callback: () => { + Core.saveSummaryAsJSON(); + } + }, + { + name: "Export Settings", + icon: '', + callback: li => { + Core.exportGameSettings(); + } + }, + { + name: "Import Settings", + icon: '', + callback: li => { + Core.importGameSettingsQuick(); + } + }, + { + name: "More options under Module Settings", + icon: '', + callback: li => { + new SettingsConfig().render(true); + } + } + ]); + } +}); diff --git a/scripts/player-settings.js b/scripts/player-settings.js new file mode 100644 index 0000000..e133dd4 --- /dev/null +++ b/scripts/player-settings.js @@ -0,0 +1,188 @@ +import { name, templates, log } from './config.js'; +import Core from './core.js' + +export default class CopyEnvironmentPlayerSettings extends FormApplication { + constructor() { + super(); + this.settings = []; + this.notFound = []; + } + + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ['copy-environment-player-settings'], + height: 'auto', + width: 600, + id: `${name}-player-settings`, + title: `${name}.forms.player-settings.title`, + template: templates.playerSettings, + tabs: [{ + navSelector: '.tabs', + contentSelector: 'form', + initial: 'export', + }] + }); + } + + getData() { + return { + settings: this.settings, + notFound: this.notFound, + users: game.users, + }; + } + + activateListeners(html) { + super.activateListeners(html); + + html.find('input[name=import-file]').on("change", this._processImportFile.bind(this)); + + html.on('click', '.export-save-player', () => { + CopyEnvironmentPlayerSettings.exportPlayers(); + this.close(); + }); + + html.on('click', '.import-players', (e) => { + for (let field of this.form.getElementsByTagName('fieldset')) { + let targetUser = null; + let changes = { + flags: {} + }; + for (let input of field.elements) { + if (!input.checked) { + continue; + } + + let target = input.dataset?.for; + if (!this.settings[target]) { + log(false, 'Import player settings: could not find target for', input); + continue; + } + + let type = input.dataset?.type; + if (!type) { + log(false, 'Import player settings: missing type (core or flag)'); + continue; + } + + if (!targetUser) { + targetUser = game.users.getName(this.settings[target].existingUser.name); + } + + if (type === 'core') { + changes[input.name] = this.settings[target].core[input.name]; + } + + if (type === 'flag') { + changes.flags[input.name] = this.settings[target].flags[input.name]; + } + } + + if (Object.keys(changes).length === 1 && Object.keys(changes.flags).length === 0) { + log(false, 'No changes selected for', targetUser?.name); + continue; + } + + log(false, `Updating ${targetUser?.name} with`, changes); + targetUser.update(changes); + + ui.notifications.info("Updated player settings for: " + targetUser.name, {}); + } + + this.close(); + }); + } + + async _updateObject(event, formData) { + log(false, event, formData); + } + + async _processImportFile() { + const file = this.form.elements['import-file'].files[0]; + if (!file) { + log(false, 'Player setting import file not found.'); + return; + } + + let app = this; + + readTextFromFile(file).then(async result => { + const existingSettings = JSON.parse(result); + log(false, 'settings', existingSettings) + log(false, 'players', game.users); + let settings = []; + let notFound = []; + for (let i = 0; i < existingSettings.length; i++) { + const setting = existingSettings[i]; + const existingUser = game.users.getName(setting.name); + if (!existingUser) { + notFound.push(setting); + continue; + } + setting.coreDiff = {}; + setting.flagDiff = {}; + + if (setting.core?.color !== existingUser.data.color) { + setting.coreDiff.color = { + name: 'color', + oldVal: existingUser.data.color, + oldString: JSON.stringify(existingUser.data.color), + newVal: setting.core.color, + newString: JSON.stringify(setting.core.color) + }; + } + + if (setting.core?.role !== existingUser.data.role) { + setting.coreDiff.role = { + name: 'role', + oldVal: existingUser.data.role, + oldString: JSON.stringify(existingUser.data.role), + newVal: setting.core.role, + newString: JSON.stringify(setting.core.role) + }; + } + + setting.existingUser = existingUser; + let flagDiff = diffObject(existingUser.data.flags, setting.flags); + + for (const prop in flagDiff) { + if (!flagDiff.hasOwnProperty(prop)) { + continue; + } + setting.flagDiff[prop] = { + name: prop, + oldVal: existingUser.data.flags[prop], + oldString: JSON.stringify(existingUser.data.flags[prop]), + newVal: flagDiff[prop], + newString: JSON.stringify(flagDiff[prop]) + }; + } + + if (Object.keys(setting.coreDiff).length === 0 && Object.keys(setting.flagDiff).length === 0) { + // No change. + continue; + } + + settings.push(setting); + } + + app.settings = settings; + app.notFound = notFound; + app.render(false); + }); + } + + static exportPlayers() { + let data = game.users.map(u => ({ + name: u.data.name, + core: { + avatar: u.data.avatar, + color: u.data.color, + permissions: u.data.permissions, + role: u.data.role + }, + flags: u.data.flags + })); + Core.download(data, 'foundry-player-settings-export.json'); + } +} diff --git a/scripts/preloadTemplates.js b/scripts/preloadTemplates.js new file mode 100644 index 0000000..d24e51e --- /dev/null +++ b/scripts/preloadTemplates.js @@ -0,0 +1,10 @@ +import { templates } from './config.js'; + +export const preloadTemplates = async function() { + + return loadTemplates( + Object.keys(templates).map(function(key){ + return templates[key]; + }) + ); +} diff --git a/scripts/prompt.js b/scripts/prompt.js deleted file mode 100644 index 44b7098..0000000 --- a/scripts/prompt.js +++ /dev/null @@ -1,154 +0,0 @@ -(() => { - const module = "Forien's Copy Environment"; - const author = "Forien"; - const message = "

Thank you for downloading our modules! We are implementing a new, unified Welcome Screen to contain information for any/all of our Foundry Workshop modules.

We strongly recommend you install it so that you are updated and notified about new versions. The new Welcome Screen is highly customizable and offers several different display options.

"; - const messageEnable = "You have installed Foundry Workshop Welcome Screen. Do you want to enable it now?"; - const disclaimer = "Clicking 'Install' will download the 'Foundry Workshop Welcome Screen' module and install it into your Foundry instance. It will also send you back to the setup screen where you will need to re-launch your world."; - const ending = "Sincerely,"; - const manifest = 'https://raw.githubusercontent.com/Foundry-Workshop/welcome-screen/master/module.json'; - const wsID = 'workshop-welcome-screen'; - - let testSetup = async () => { - let response = {}; - try { - response = await fetch(SetupConfiguration.setupURL, { - method: "POST", - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({}) - }); - } catch (e) { - return false; - } - - return response.status !== 403; - }; - - let tryInstall = async () => { - let test = await testSetup(); - - if (test === true) { - ui.notifications.active = []; - ui.notifications.info("Preparing to download module…", {permanent: true}); - const notif = ui.notifications.active[0]; - game.socket.on("progress", data => { - notif.html(data.msg); - }); - await SetupConfiguration.installPackage({type: "module", manifest: manifest}); - await game.shutDown(); - } else { - new Dialog({ - title: `Foundry is protected`, - content: `

Your Foundry VTT instance's setup is password protected (which is good!). Because of it, you need to 'back to setup' and install the module manually, or come back after you login as an administrator.

Click on the link below to copy it:

`, - buttons: { - shutdown: { - label: "Back to Setup", - callback: () => { - game.shutDown(); - } - }, - close: { - label: "Close", - } - } - })._render(true).then(() => { - document.getElementById("workshop-welcome-screen-manifest").onclick = function () { - this.select(); - document.execCommand('copy'); - ui.notifications.info("Manifest URL copied!", {}); - } - }); - } - }; - - let installPrompt = () => { - if (window.workshopWS.app) return; - game.settings.register(wsID, 'showPrompt', {scope: "client", config: false, default: true}); - if (!game.settings.get(wsID, 'showPrompt')) return; - - let authors = Object.keys(window.workshopWS.authors).join(' and '); - let modules = window.workshopWS.modules.map(m => `
  • ${m}
  • `).join(''); - - window.workshopWS.app = new Dialog({ - title: `Install Welcome Screen for Foundry Workshop's modules?`, - content: `${message}
    Installed modules:
      ${modules}

    ${ending}
    ${authors}

    ${disclaimer}

    `, - buttons: { - cancel: { - label: "No" - }, - never: { - label: "Never show again", - callback: () => { - game.settings.set(wsID, 'showPrompt', false) - } - }, - install: { - label: "Install", - callback: () => { - tryInstall() - } - } - }, - default: 'install' - }, - {id: `${wsID}-install-prompt`, width: 420, height: 540}); - window.workshopWS.app.render(true); - }; - - let enablePrompt = () => { - if (window.workshopWS.app) return; - game.settings.register(wsID, 'showPrompt', {scope: "client", config: false, default: true}); - if (!game.settings.get(wsID, 'showPrompt')) return; - - window.workshopWS.app = new Dialog({ - title: `Enable Welcome Screen?`, - content: `

    ${messageEnable}

    `, - buttons: { - cancel: { - label: "No" - }, - never: { - label: "Never show again", - callback: () => { - game.settings.set(wsID, 'showPrompt', false) - } - }, - install: { - label: "Enable", - callback: () => { - const settings = game.settings.get("core", ModuleManagement.CONFIG_SETTING); - const setting = mergeObject(settings, {[wsID]: true}); - game.settings.set("core", ModuleManagement.CONFIG_SETTING, setting); - } - } - }, - default: 'install' - }); - window.workshopWS.app.render(true); - }; - - Hooks.on("init", () => { - if (window.workshopWS === undefined) { - window.workshopWS = { - modules: [module], - authors: { - [author]: true - }, - app: undefined - }; - } else { - window.workshopWS.modules.push(module); - window.workshopWS.authors[author] = true; - } - }); - - Hooks.on("ready", () => { - if (!game.user.isGM) return; - - const ws = game.modules.get(wsID); - if (ws === undefined) { - installPrompt(); - } else if (!ws.active) { - enablePrompt(); - } - }); -})(); \ No newline at end of file diff --git a/styles/module.css b/styles/module.css new file mode 100644 index 0000000..2a53089 --- /dev/null +++ b/styles/module.css @@ -0,0 +1,13 @@ +@charset "UTF-8"; +.copy-environment-player-settings form .form-group .form-fields { + flex: 1; +} +.copy-environment-player-settings .tabs, +.copy-environment-world-settings .tabs { + font-size: 14px; + padding-bottom: 0.3em; + border-bottom: 1px solid #000; +} +#forien-copy-environment-player-settings td.value { + word-break: break-all; +} \ No newline at end of file diff --git a/templates/player-settings.html b/templates/player-settings.html new file mode 100644 index 0000000..d12e8ea --- /dev/null +++ b/templates/player-settings.html @@ -0,0 +1,91 @@ +
    +
    + + +
    +
    +

    {{localize 'forien-copy-environment.forms.player-settings.export.playerList'}}

    +
      + {{#each users}} +
    • {{ data.name }}
    • + {{/each}} +
    +
    + +
    + + +
    +
    + +
    +
    + {{#unless settings}} +

    {{localize 'forien-copy-environment.forms.player-settings.import.existing'}}

    +
    + +
    + {{/unless}} + + {{#if settings}} +

    {{localize 'forien-copy-environment.forms.player-settings.import.playerList'}}

    + {{#each settings}} +
    + {{ name }} + + + + + + + + {{#each coreDiff}} + + + + + + {{/each}} + {{#each flagDiff}} + + + + + + {{/each}} + +
    {{localize 'forien-copy-environment.forms.player-settings.import.property'}}{{localize 'forien-copy-environment.forms.player-settings.import.newValue'}}{{localize 'forien-copy-environment.forms.player-settings.import.currentValue'}}
    + {{ newString }} + + {{ oldString }} +
    + {{ newString }} + + {{ oldString }} +
    +
    + {{/each}} + {{/if}} + + {{#if notFound}} +

    {{localize 'forien-copy-environment.forms.player-settings.import.notFound'}}

    +
      + {{#each notFound}} +
    • {{ name }}
    • + {{/each}} +
    + {{/if}} +
    + +
    + {{#if settings}}{{/if}} + +
    +
    +
    +
    \ No newline at end of file diff --git a/templates/world-settings.html b/templates/world-settings.html new file mode 100644 index 0000000..374e796 --- /dev/null +++ b/templates/world-settings.html @@ -0,0 +1,35 @@ +
    +
    + + +
    +
    +

    {{localize 'forien-copy-environment.forms.world.settings.intro'}}

    +

    {{localize 'forien-copy-environment.forms.world.settings.exportIntro'}}:

    +

    {{localize 'forien-copy-environment.forms.world.settings.importIntro'}}:

    +
    + +
    + +
    +
    + +
    +
    +

    {{localize 'forien-copy-environment.forms.world.environment.intro'}}

    +

    {{localize 'forien-copy-environment.forms.world.environment.copyIntro'}}:

    +

    {{localize 'forien-copy-environment.forms.world.environment.exportIntro'}}:

    +

    {{localize 'forien-copy-environment.forms.world.environment.importIntro'}}

    +
    + +
    + +
    +
    +
    +
    \ No newline at end of file From 775e334cd48d67a4477b935aff92f986dd00f61b Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Fri, 12 Mar 2021 12:22:51 +1000 Subject: [PATCH 2/3] Convert to league release process --- .github/workflows/main.yml | 40 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 41 ----------------------------------- 2 files changed, 40 insertions(+), 41 deletions(-) create mode 100644 .github/workflows/main.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..b9043a7 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,40 @@ +name: Release Creation + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + # Substitute the Manifest and Download URLs in the module.json + - name: Substitute Manifest and Download Links For Versioned Ones + id: sub_manifest_link_version + uses: microsoft/variable-substitution@v1 + with: + files: 'module.json' + env: + version: ${{github.event.release.tag_name}} + url: https://github.com/${{github.repository}} + manifest: https://github.com/${{github.repository}}/releases/latest/download/module.json + download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip + + # Create a zip file with all files required by the module to add to the release + - run: zip -r ./module.zip module.json styles/ scripts/ templates/ languages/ + + # Create a release for this specific version + - name: Update Release with Files + id: create_version_release + uses: ncipollo/release-action@v1 + with: + allowUpdates: true # Set this to false if you want to prevent updating existing releases + name: ${{ github.event.release.name }} + draft: false + prerelease: false + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: './module.json, ./module.zip' + tag: ${{ github.event.release.tag_name }} + body: ${{ github.event.release.body }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 62d172a..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,41 +0,0 @@ -on: - push: - # Sequence of patterns matched against refs/tags - tags: - - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 - -name: Upload Release Asset - -jobs: - build: - name: Upload Release Asset - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Get version - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF#refs/*/} - - name: Zip files - run: | - zip -r ${{ steps.get_version.outputs.VERSION }}.zip * - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1.0.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./${{ steps.get_version.outputs.VERSION }}.zip - asset_name: ${{ steps.get_version.outputs.VERSION }}.zip - asset_content_type: application/zip From 520dc632e7b17da9bc400407f527afe838f9cf10 Mon Sep 17 00:00:00 2001 From: Blair McMillan Date: Mon, 15 Mar 2021 12:24:33 +1000 Subject: [PATCH 3/3] Tested against v0.6.0 and v.0.8.0 --- module.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module.json b/module.json index ea7a80b..646e8de 100644 --- a/module.json +++ b/module.json @@ -5,8 +5,8 @@ "version": "2.0.0", "library": "false", "manifestPlusVersion": "1.0.0", - "minimumCoreVersion": "0.7.6", - "compatibleCoreVersion": "0.7.9", + "minimumCoreVersion": "0.6.0", + "compatibleCoreVersion": "0.8.0", "author": "Forien — Forien#2130", "authors": [ {