const LOG_PREFIX = "asc-asset-manager | " import { registerSettings } from "./settings.js"; import { parseFileName, createMetaFileName } from "./utils.js"; export class AscAssetManager { static ID = 'asc-asset-manager' static TEMPLATES = { UPLOAD_CHOOSE:`modules/${this.ID}/templates/upload-choose.hbs`, UPLOAD_FORM:`modules/${this.ID}/templates/upload-form.hbs`, SETTINGS_MENU_MACRO:`modules/${this.ID}/templates/settings-menu-macro.hbs`, SETTINGS_TAGS_AND_CATEGORIES:`modules/${this.ID}/templates/settings-tags-and-categories.hbs` } static getDirectory () { return game.settings.get(this.ID, "rootDirectory") } static fileCategories = [ {id: "npcn", label: "NPC (Named)"}, {id: "npcu", label: "NPC (Unnamed)"}, {id: "scene", label: "Scene Background"}, {id: "pc", label: "PC"}, {id: "inset", label: "Inset"}, {id: "vehicle", label: "Vehicle"}, {id: "weapon", label: "Weapon"} ] static fileTags = [ {id:"tk", label: "Token"}, {id:"sq", label: "Square"} ] static log(force, ...args) { console.log(this.ID, '|', ...args); } } Hooks.on('init', ()=>{ } ) Hooks.on("ready", function() { registerSettings(AscAssetManager); const DEBUG = game.settings.get(AscAssetManager.ID, "enableDebugMode") if (DEBUG) { AscAssetManager.log(false, "Debug Mode Enabled") CONFIG.debug.hooks = true } AscAssetManager.log(false, "Deno nodule reody") }); Hooks.on("ascAssetManager.renderUploadChoose", (data={}) => { let {files} = data renderTemplate(AscAssetManager.TEMPLATES.UPLOAD_CHOOSE, {moduleId: AscAssetManager.ID}).then((content)=>{ const dialog = new Dialog({ title: "Choose", content: content, buttons: [], render: (html)=> { AscAssetManager.log(false, 'Rendering choose window') const uploadArea = html.find("#upload-area"); const fileInput = html.find("#file-input"); const form = html.find("form") if (files) { fileInput.val(files) } // Handle drag-and-drop events uploadArea.on("dragover", (event) => { event.preventDefault(); uploadArea.addClass('dragover') }); uploadArea.on("dragleave", () => { uploadArea.removeClass('dragover') }); uploadArea.on("drop", (event) => { event.preventDefault(); // uploadArea.css("background-color", ""); const files = event.originalEvent.dataTransfer.files; if (files.length > 0) { AscAssetManager.log(false, 'file dropped change') // Update the file input with the dropped file const dataTransfer = new DataTransfer(); for (let file of files) { dataTransfer.items.add(file); // Add the first dropped file } fileInput.files = dataTransfer.files; for (let file of fileInput.files) { Hooks.callAll("ascAssetManager.renderUploadForm", {file}) } } }); fileInput.on("change", (event)=> { const files = fileInput.files // Show feedback to the user uploadArea.find("p").text(`Selected file: ${Array.from(files).map(f=>f.name).join(', ')}`); }) } }).render(true) }) }) Hooks.on("renderHotbar", ({macros}, html) => { // Find macro on the hotbar for (let macro_item of macros) { const {macro} = macro_item if (macro?.command?.includes("ascAssetManager.renderUploadChoose")) { AscAssetManager.log(false, `Found macro with command: ${macro.name}`); // Find the corresponding button in the hotbar const macroButton = html.find(`.macro[data-macro-id='${macro.id}']`); if (macroButton.length > 0) { AscAssetManager.log(false, `Adding custom drop event to macro: ${macro.name}`, {macro, macroButton}); macroButton.addClass(AscAssetManager.ID) macroButton.on('dragover', (event)=>{ AscAssetManager.log(false, {event}); $(event.currentTarget).addClass('dragover'); AscAssetManager.log(false, {classlist: event.currentTarget.classList}); }) macroButton.on('dragleave', (event)=>$(event.currentTarget).removeClass('dragover')) // Add a custom drop event to the macro macroButton.on("drop", (event) => { event.preventDefault(); $(event.currentTarget).removeClass('dragover') const files = event.originalEvent.dataTransfer.files; AscAssetManager.log(false, "Dropped file on macro.", {files}); for (let file of files) { Hooks.callAll("ascAssetManager.renderUploadForm", {file}) } // Perform your custom logic with the dropped data // handleCustomDrop(droppedData, macro); }); } } } }); Hooks.on("ascAssetManager.renderUploadForm", (data={})=>{ const templateData = { moduleId: AscAssetManager.ID, fileCategories: game.settings.get(AscAssetManager.ID, "categories"), fileTags: game.settings.get(AscAssetManager.ID, "tags") } renderTemplate(AscAssetManager.TEMPLATES.UPLOAD_FORM, templateData).then(content => { let {file} = data const dialog = new Dialog({ title: "Simple Popup", content: content, buttons: [], render: (html) =>{ AscAssetManager.log('file', file) const uploadArea = html.find("#upload-area"); const fileInput = html.find("#file-input"); const form = html.find('#upload-form'); const namePreview = html.find('#name-preview') const baseName = form.find("input[id='baseName']") fileInput.val(file.name) const reader = new FileReader(); reader.onload = (e) => { const img = form.find("img"); const blob = new Blob([e.target.result], { type: file.type }); const blobUrl = URL.createObjectURL(blob) AscAssetManager.log(false, blobUrl,img) img.attr("src", blobUrl) }; reader.readAsArrayBuffer(file) baseName.val(parseFileName(file.name).fileName) // Handle click to open file selector // uploadArea.on("click", () => fileInput.click()); form.on('change', (event)=>{ const fileExtension = parseFileName(fileInput.val()).fileExtension const fileCategory = form.find("select[name='file-category'] option:checked").val() const fileTags = form.find("input[name='file-tags']:checked").map(function(){ return $(this).val() }).get() AscAssetManager.log(false, 'form changed', {fileCategory, fileTags, baseName}) const new_filename = createMetaFileName(`${baseName.val()}.${fileExtension}`,{ category: fileCategory, tags: fileTags }) namePreview.val(new_filename) }) form.on('submit', (event) => { AscAssetManager.log(false, "Form Submitted"); event.preventDefault(); const renamedFile = new File([file], namePreview.val(), {type:file.type}) FilePicker.upload( "data", AscAssetManager.getDirectory(), renamedFile, { notify: true } ) .then((res)=>{ AscAssetManager.log(false, 'Uploaded!', res); dialog.close() }) .catch((e)=>ui.notifications.error('Error uploading', e)) }) } }).render(true); }) })