No internet connection
  1. Home
  2. How to

Undo History won't clear if popupmenu checked

By Forrester Savell @Forrester_Savell
    2024-10-28 03:43:22.588Z

    Hello

    I've a simple script that clears the Undo History queue. If I comment out lines 13-25, the script works fine, but if I check to see if the "Clear Undo Queue" menuitem is enabled, the script fails with 'Popup menu was not found'. I've confirmed it is enabled and there are Undo steps in the queue.
    Specifically, if I have the line const undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems().menuItems, it breaks. How does fetching the popupmenu cause the popupMenuSelect to fail?

    What am I doing wrong here?

    sf.ui.proTools.appActivateMainWindow();
    log('Attempting to clear Undo History...');
    
    // Open the Undo History window
    sf.ui.proTools.menuClick({ menuPath: ["Window", "Undo History"], targetValue: "Enable" });
    
    // Define the Undo History button that opens the menu
    const undoHistoryBtn = sf.ui.proTools.windows.whoseTitle.is("Undo History").first
        .children.whoseRole.is("AXMenuButton").whoseTitle.is("Undo Actions").first;
    
    
    // This below section of code works correctly if the "Clear Undo Queue" button is greyed out, but fails if it's not
    /* // Fetch all enabled menu items for the undo history button
    let undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems().menuItems
        .filter(mi => mi.element.isEnabled)
        .map(mi => mi.path.join(" > ")); 
    
    log(undoHistoryMenu)
    
    // Check if "Clear Undo Queue" exists in the enabled menu items
    if (!undoHistoryMenu.includes("Clear Undo Queue")) {
        log("No Undo History to delete.");
        throw 0; // Exit if no Undo History items are available to delete
    }  */
    
    // Otherwise, clear the undo queue
    undoHistoryBtn.popupMenuSelect({
        menuPath: ["Clear Undo Queue"],
    });
    
    // Confirm the action if a confirmation dialog appears
    if (sf.ui.proTools.confirmationDialog.exists) {
        const yesButton = sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("Yes").first;
        if (yesButton.exists) {
            yesButton.elementClick();
            sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Disappear" });
        }
    }
    
    log('Undo History cleared.');
    
    // Close the Undo History window
    sf.ui.proTools.menuClick({ menuPath: ["Window", "Undo History"], targetValue: "Disable" });
    
    Solved in post #2, click to view
    • 9 replies
    1. Give this a try:

      sf.ui.proTools.appActivateMainWindow();
      sf.ui.proTools.mainWindow.invalidate();
      
      log('Attempting to clear Undo History...');
      
      // Open the Undo History window
      sf.ui.proTools.menuClick({ menuPath: ["Window", "Undo History"], targetValue: "Enable" });
      
      // Define the Undo History button that opens the menu
      const undoHistoryWin = sf.ui.proTools.windows.whoseTitle.is("Undo History").first;
      
      undoHistoryWin.elementWaitFor();
      
      const undoHistoryPopupBtn = undoHistoryWin.children.whoseRole.is("AXMenuButton").whoseTitle.is("Undo Actions").first;
      
      const isClearEnabled = undoHistoryPopupBtn.popupMenuSelect({
          menuSelector: items => items.find(mi => mi.path[0] === "Clear Undo Queue" && mi.element.exists && mi.element.isEnabled)
      }, () => log("No Undo History to Clear")).success;
      
      if (isClearEnabled) {
          const yesBtn = sf.ui.proTools.focusedWindow.buttons.whoseTitle.is("Yes").first;
          sf.waitFor({
              callback: () => {
                  sf.wait({intervalMs:150})
                  sf.ui.proTools.windows.invalidate()
                  return yesBtn.exists
              }
          })
          yesBtn.elementClick();
          log("Undo History Cleared")
      
      }
      
      // Close the Undo History window
      sf.ui.proTools.menuClick({ menuPath: ["Window", "Undo History"], targetValue: "Disable" });
      
      ReplySolution
      1. Line 16 does a few things:
        It looks for a "Clear Undo Queue" menu item that exists and is enabled and attempts to click it.
        If it doesn't exist it logs "No Undo History to Clear" and sets `isClearEnabled" to false.

        The rest should be self explanatory

        1. In reply toChris_Shaw:

          You might have been getting an error because the script wasn't waiting for the Undo History window to open before fetching the popup menu items.

          1. FForrester Savell @Forrester_Savell
              2024-10-28 22:12:40.514Z

              Thanks Chris.

              Your script works great. I'm still a bit baffled by the error on mine. Even if the window is already visible, or if I add

              const undoHistoryWin = sf.ui.proTools.windows.whoseTitle.is("Undo History").first;
              
              undoHistoryWin.elementWaitFor();
              

              it still gives the popupmenu error if it creates the undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems().menuItems variable.

              Also I have a followup question - I pulled the popupMenuFetchAllItems().menuItems.filter(mi => mi.element.isEnabled) from another forum post (Exclude Greyed out options from a pop up menu in popup search #post-2) relating to identifying greyed-out menu items. Where is the isEnabled getting its information from? If I log the undoHistoryMenu, none of the information changes whether the menu items are greyed out or not.

              1. I think the issue may be here (line 14):

                let undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems().menuItems
                    .filter(mi => mi.element.isEnabled)
                    .map(mi => mi.path.join(" > ")); 
                

                If you put a throw 0 after this at line 17 the popup menu stays open. I'm thinking that when SF tries to click the clear the Undo Queue (line 27) it cannot find the popup button because the menu is still open.
                Try adding a dismissMenu: true at line 14 like this:

                let undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems({dismissMenu:true}).menuItems
                    .filter(mi => mi.element.isEnabled)
                    .map(mi => mi.path.join(" > ")); 
                
                1. On my system (2024.6 / Ventura/ SF 5.9 - you can manually download this now) I don't have any issue other than the script doesn't click the "Yes" button in the confirmation window. That's why I wrote an alternate routine to detect it.
                  Without seeing your script in action and failing I can't be 100% sure of where the fault is happening other than what I described above.

                  1. Out of curiosity, what MacOS/PT/SF versions are you running?

                    1. FForrester Savell @Forrester_Savell
                        2024-10-29 01:45:04.260Z

                        I'm running SF 5.9.0, macOS 13.6.3 and yesterday I was running PT2024.6 and have tried 2024.10 this morning. Same results.

                    2. In reply toChris_Shaw:
                      FForrester Savell @Forrester_Savell
                        2024-10-28 23:33:42.455Z

                        That makes sense, but its not solving it. If I use

                        let undoHistoryMenu = undoHistoryBtn.popupMenuFetchAllItems({ dismissMenu: true }).menuItems
                            .filter(mi => mi.element.isEnabled)
                            .map(mi => mi.path.join(" > "));
                        
                        log(undoHistoryMenu)
                        

                        it causes the undoHistoryMenu array to be empty. Perhaps its something to do with popupMenuFetchAllItems vs popupMenuSelect?

                        I think it will remain a mystery, as your code works well. Thanks for you help Chris.