No internet connection
  1. Home
  2. How to

How to Open / Hide App

By Masayoshi Sugai @Masayoshi_Sugai
    2021-09-16 01:15:47.916Z2021-09-16 21:18:35.189Z

    Hi All!
    I'm trying to make a script that opens and hides a Mac App. The target is an App like Safari where the App does not Quit even if the window is closed, and the window opens again the next time the App icon in the Dock is clicked. (Safari, Mail, Chrome, etc.)
    But the script I made is a little different from what I want.
    Now it is below.

    if (!sf.ui.app('com.apple.Safari').mainWindow.exists) {
        sf.app.launch({
            path: "/Applications/Safari.app",
        });
        globalState.messagesIsOpen = true
        throw 0
    }
    if (globalState.messagesIsOpen == true) {
        sf.ui.app('com.apple.Safari').menuClick({
            menuPath: ["Safari", "Hide Safari"],
        });
        globalState.messagesIsOpen = false
        throw 0
    }
    
    sf.ui.app('com.apple.Safari').appActivateMainWindow();
    globalState.messagesIsOpen = true;
    

    What I want is:
    (a) .Safari is not launching> Launch (& new window)… OK
    (b). Safari is running and the window in the foreground> Hide… OK
    (c) .Hide> Show Safari… OK
    (d) .Safari is launched and is in the foreground, but there is no window> New window ... OK
    (e) .Safari is running and a window is displayed, but other apps are in the foreground (Safari window behind it)> Safari is hidden once, so I have to press the button twice.

    What I want to do is improve the behavior of (e), and at this time I want Safari to come to the foreground instead of being hidden by pressing the button once.

    Does anyone have an idea?

    Solved in post #7, click to view
    • 6 replies
    1. Chris Shaw @Chris_Shaw2021-09-16 23:32:55.873Z2021-09-17 00:19:34.820Z

      this should do it:

      const safari = sf.ui.app('com.apple.Safari');
      if (!safari.isActive) {
          sf.app.launch({
              path: "/Applications/Safari.app",
          });
          globalState.safariIsFocused = true
          throw 0
      };
      
      if (safari.isActive && globalState.safariIsFocused) {
          safari.menuClick({
              menuPath: ["Safari", "Hide Safari"],
          });
          globalState.safariIsFocused = false
          throw 0
      };
      if (!safari.isActive && !globalState.safariIsFocused) {
          // if Safari is open but no window is open, then a launch command forces a new window to open
          // If Safari is open and a window is open it will activate the main window
          sf.app.launch({
              path: "/Applications/Safari.app",
          });
          globalState.safariIsFocused = true;
      }
      // This will activate the Safari window again so you don't have to press your trigger twice
      safari.appActivateMainWindow();
      globalState.safariIsFocused = true;
      
      
      1. In reply toMasayoshi_Sugai:
        Kitch Membery @Kitch2021-09-16 23:51:42.449Z2021-09-17 03:32:23.178Z

        Hi @Masayoshi_Sugai,

        Here is a version without having to use using globalstate. Fun stuff :-)

        const appName = 'Safari';
        const appRef = sf.ui.app('com.apple.Safari');
        const appPath = '/Applications/Safari.app';
        
        const isAppRunning = appRef.isRunning;
        const isAppFrontmost = sf.ui.frontmostApp.uiElement['Title'] === appName;
        const isAppWindowOpen = appRef.windows.length > 0;
        
        switch (true) {
            case (!isAppRunning):
                sf.app.launch({ path: appPath });
                break
            case (!isAppFrontmost && isAppWindowOpen):
                sf.app.launch({ path: appPath });
                break
            case ((!isAppFrontmost || isAppFrontmost) && !isAppWindowOpen):
                appRef.appActivate();
                appRef.menuClick({ menuPath: ['File', 'New Window'] });
                break
            case (isAppFrontmost && isAppWindowOpen):
                appRef.menuClick({
                    menuPath: [appName, `Hide ${appName}`],
                });
                break
        }
        

        Rock on!

        Updated: Fixed reference to appName in line 25 and refactored. :-)

        1. Good one Kitch!

        2. M
          In reply toMasayoshi_Sugai:
          Masayoshi Sugai @Masayoshi_Sugai
            2021-09-17 01:38:08.961Z

            Hello Chris and Kitch. Thank you for your help!
            wonderful! Now I can apply it to almost all apps!
            One thing, I want the EuControl App to behave in the same way, but I can't automatically open the EuControl Settings Window that was closed once while the App was running.Currently I have to manually open the window with ⌘ + 1.
            Here is the script.

            const appName = 'EuControl';
            const appRef = sf.ui.app('com.Euphonix.EuControl');
            const appPath = '/Applications/EuControl.app';

            const isAppRunning = appRef.isRunning;
            const isAppFrontmost = sf.ui.frontmostApp.uiElement['Title'] === appName;
            const isAppWindowOpen = appRef.windows.length > 0;

            switch (true) {
            case (!isAppRunning):
            sf.app.launch({ path: appPath });
            break
            case (isAppRunning && !isAppFrontmost && isAppWindowOpen):
            sf.app.launch({ path: appPath });
            break
            case (isAppRunning && !isAppFrontmost && !isAppWindowOpen):
            appRef.appActivate();
            appRef.menuClick({ menuPath: ['Window', 'EuControl Settings'] });
            break
            case (isAppRunning && isAppFrontmost && !isAppWindowOpen):
            appRef.menuClick({ menuPath: ['Window', 'EuControl Settings'] });
            break
            case (isAppRunning && isAppFrontmost && isAppWindowOpen):
            appRef.menuClick({
            menuPath: ["EuControl", "Hide EuControl"],
            });
            break
            }

            appRef.menuClick ({menuPath: ['Window','EuControl Settings']});
            This doesn't seem to work, am I doing something wrong?

            1. MMasayoshi Sugai @Masayoshi_Sugai
                2021-09-17 15:55:21.249Z

                I solved it!

                I made the following changes and it worked as expected.

                from
                const isAppWindowOpen = appRef.windows.length> 0;
                to
                const isAppWindowOpen = appRef.windows.length> 1;

                Thank you everyone for your help!

                ReplySolution
              • In reply toMasayoshi_Sugai:

                Riffing on this, I'd love to have a command that hides all apps except Pro Tools, Dolby Atmos Renderer and Avid Control Desktop. I'll work on this later, but if someone more clever than me has this figured out, please post. Thanks!