Mini Kabibi Habibi

Current Path : C:/Program Files/Adobe/Adobe Photoshop 2025/Required/UXP/com.adobe.photoshop.infoAlert/
Upload File :
Current File : C:/Program Files/Adobe/Adobe Photoshop 2025/Required/UXP/com.adobe.photoshop.infoAlert/index.js

//
// Copyright 2023 Adobe, Inc. All Rights Reserved.
//
// This is generic code to display an "info" box, usually invoked by
// pressing an ⓘ button. The position of the dialog relative to the app
// is given by the leftoffset, topoffset attributes.
//
// 100+ lines of code to - display a dialog. Where did we go wrong?
//

const uxp             = require("uxp");
const photoshop       = require("photoshop");

// I'm kinda missing jQuery
$getID = (key) => document.querySelector(key);
$getList = (key) => document.querySelectorAll(key);

// Searches up the parent tree for a paricular tag (DIV, DIALOG, FORM, etc.)
function getParentByTag(item, tag)
{
  var curItem = item.parentElement;
  while (curItem && (curItem.tagName != tag))
    curItem = curItem.parentElement;
  return curItem;
}

///////////////////////////////////////////////////////////
// User interface
///////////////////////////////////////////////////////////

// Debug - used to make the first cut of the localization file from the HTML
function makeLocalizeJSON()
{
  let locItems = $getList(".loc");
  locItems.forEach( function(item)
  {
    // "commit_new_layer": "Nytt lag",
    if (item.tagName == "SP-BODY") {
        // The body is handled as a block of HTML so the formatting is retained.
        console.log('"'+item.id + '": "'+ item.innerHTML.replace("\n", " ")+'",');
    }
    else
        console.log('"'+item.id+'": "'+item.textContent+'",');
  })
}

// UXP can only position dialogs by raw screen coordinates. This fetches the location
// of the PS application frame, so we can adjust the coordinates relative to that frame.
async function getAppCoords(alertID)
{
 // Determine staging vs. production at startup; set global flag.
    // First, check if we're on pre-release or release....
    let getFrameDesc = {"_obj": "owlAction",
                        "_target":[{"_enum":"ordinal", "_ref":"application", "_value":"targetEnum"}],
                        "owlCommand":"getApplicationFrameInfo"};

    let frameDesc = await photoshop.action.batchPlay( [getFrameDesc], {} );
    let appRect = frameDesc[0].globalBounds;

    // Once we have the frame, invoke the alert display in a then() clause.
    // Then only allows one arg, so we have to mush the parameters together.
    return new Promise( function(resolve, reject) {
        resolve({"id":alertID, "bounds":appRect});
    });
}

// Open the Info dialog
function displayInfoDialog(args)
{
    let alertID = args.id;
    let appRect = args.bounds;
    let dialog = $getID("#" + alertID);
    let offset = {left: appRect.left + Number(dialog.getAttribute("leftoffset")), 
                  top: appRect.top + Number(dialog.getAttribute("topoffset"))};

    dialog.show( {
      titleVisibility: "hide",
      title: photoshop.core.translateUIString( "$$$/Photoshop/infoDialog/dialogTitle=Information" ),
      anchorOffset: offset});
  
    // Hide the debug button, if present
    let debugButton = $getID("#debug");
    if (debugButton)
        debugButton.style.display = 'none';

    // Run all of the text through localization
    let locItems = $getList(".loc");
    locItems.forEach( function(item)
    {
        if (item.tagName == "SP-BODY")
            // The body is handled as a block of HTML so the formatting is retained.
            item.innerHTML = photoshop.core.translateUIString( "$$$/Photoshop/infoAlert/"+item.id+"="+item.innerHTML);
        else
            item.textContent = photoshop.core.translateUIString( "$$$/Photoshop/infoAlert/"+item.id+"="+item.textContent);
    });
}

function runDisplayInfoDialog(alertID)
{
    getAppCoords(alertID).then(displayInfoDialog);
}

// Walk through all of the close buttons, and give them a close onclick() method
$getList(".closebutton").forEach( function( button) {
    button.onclick = function() { getParentByTag(this, "DIALOG").close(); }
});

// Debug button (normally hidden). This is a way of testing
// functionality w/o closing & re-opening the panel.
var debugButton = $getID("#debug");
if (debugButton)
    debugButton.onclick = function()
    {
        console.log("Stop here to debug");
        console.log("done");
    }

// Entry points invoked from Photoshop. The ID corresponds to the alert invoked.
// Must match the ID in the HTML.

// Add a separate entry for each dialog added.
function displayCropFillInfo() { runDisplayInfoDialog("cropFillInfo"); }

// This seems to be just window dressing. The actual entry point is
// determined by the call to InvokeSynchronousExtensionCommand in
// Photoshop

function infoAlertInit() {}

uxp.entrypoints.setup({
  commands: {
    infoAlert: () => infoAlertInit()
  }
});