brunerd / shui

shui is a shell script wrapper for presenting user dialogs in Applescript without needing to know Applescript
MIT License
30 stars 0 forks source link

Suggestion: Add Progress Window #1

Open PicoMitchell opened 3 years ago

PicoMitchell commented 3 years ago

I think a very valuable and cool usages of shui would be to be able to open the AppleScript progress window via command line. This cannot be done using osascript commands since the progress window only works with a compiled applet. But, I'm suggesting that shui could handle that complexity and create an applet on the fly using osacompile and then launch the compiled app to display progress. If you made the code of this compiled applet flexible, shui could interact with it (adjusting progress bar a text displayed) by writing to a file that the progress app reads in a loop to update the progress. I think since this is something that cannot be done with osascript, it would make it an even more appealing feature for folks who are using shui because they don't want to get into having to deal with AppleScript and especially compiling AppleScript applets themselves.

Here is a super quick proof of concept one-liner which creates a headless applet and displays indeterminate progress for 10 seconds: rm -rf "${TMPDIR}Script Progress.app"; osacompile -e 'activate' -e 'set progress description to "10 Seconds of Progress"' -e 'delay 10' -o "${TMPDIR}Script Progress.app"; plutil -insert LSUIElement -bool true "${TMPDIR}Script Progress.app/Contents/Info.plist"; open -na "${TMPDIR}Script Progress.app" (and don't forget to rm -rf "${TMPDIR}Script Progress.app" when you're done playing with this demo progress app)

PicoMitchell commented 3 years ago

If you do end up getting into this, you may run into the AppleScript progress bug in Big Sur and newer where indeterminate progress does not work after determinate progress has been shown (it just sits at 0 progress instead of animating).

Here is some example code showing that issue and a workaround via ObjC bridge to manually start the progress bar animation (this must be saved as an applet and run as an app to work):

use AppleScript version "2.4"
use scripting additions
use framework "Cocoa"

set progress description to "Testing Indeterminate Progress for 3 Seconds…"
set progress additional description to "This Works the First Time (BUT WON'T WORK THE SECOND TIME)…"
set progress total steps to -1

delay 3

set progress total steps to 5
set progress completed steps to 0
set progress description to "Now Doing Some Determinate Progress…"
set progress additional description to "0 of 5"
delay 1
repeat with thisStep from 1 to 5
    delay 1
    set progress completed steps to thisStep
    set progress additional description to (thisStep & " of 5")
end repeat
delay 2

set progress description to "Testing Indeterminate Progress Again…"
set progress additional description to "This DOES NOT Work the SECOND Time (Just Sits at 0 Progress)…"
set progress total steps to -1

delay 5

set progress additional description to "BUT, Indeterminate Progress CAN Work Again by Directly Calling \"NSProgressIndicator startAnimation\" via Cocoa…"

try
    repeat with thisWindow in (current application's NSApp's |windows|())
        if (thisWindow's isVisible() is true) then
            if (((thisWindow's title()) as string) is equal to (name of me)) then
                repeat with thisProgressWindowSubView in ((thisWindow's contentView())'s subviews())
                    if (((thisProgressWindowSubView's className()) as string) is equal to "NSProgressIndicator") then
                        (thisProgressWindowSubView's startAnimation:thisProgressWindowSubView)
                        exit repeat
                    end if
                end repeat
            end if
        end if
    end repeat
end try

delay 10

And, as is the way with AppleScript, there are few behavioral quirks to be aware of when using ObjC bridge by adding use framework "Cocoa" to your script: https://forum.latenightsw.com/t/scripting-additions-conflicting-with-cocoa/2315

And if you decide to write the progress app in JXA, I've got similar ObjC bridge code to modify the progress window in JXA that I could share with you.

Other nice things that can be done using this kind of technique to modify the progress window using ObjC bridge (in JXA or AppleScript) is to disable the Stop button, change the text of the Stop button, disable or hide any of the standard window buttons, and set the window level.