Skip to content

Honour the close settings when quitting from the tray #4068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 commit merged into from
Jun 4, 2025

Conversation

ghost
Copy link

@ghost ghost commented May 1, 2025

Closes: #3919
Previously, the tray menu action 'Quit' caused a function to immediately destroy the window. Now the usual process of closing window is taking place. This allows to consider the settings and perform the necessary tasks before closing.

Additionally, the restoration functionality of a hidden/minimized window has been added if there is a setting of the need to show a dialog before closing ('Ask about running instances').

To reproduce:
Set setting 'Stop running instances' or 'Ask about running instances'
settings

Launch instance:
run1_gui

Don't close the app Window, but Quit from the tray.

Before:
multipass_#3919_before

After:
multipass_#3919_after

@ricab
Copy link
Collaborator

ricab commented May 2, 2025

Nice, thank you @Artem-OSSRevival!

It looks like the Lint job is failing in CI. Would you mind formatting the code as recommended in the log?

@ghost ghost force-pushed the t78231 branch from eaae4ba to b76e4ca Compare May 2, 2025 14:55
Copy link
Collaborator

@ricab ricab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Artem-OSSRevival, thank you for the PR!

This is certainly an improvement. There is only a case that I am thinking we could handle better (comment inline). I would like to know your thoughts.

Also, it appears you haven't signed the CLA yet? Would you mind doing so, please?

Comment on lines 190 to 193
if (!await windowManager.isVisible() ||
await windowManager.isMinimized()) {
windowManager.showAndRestore();
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am debating whether the window should be shown also when stopping all instances (case stop). It can take a while to stop all instances. If the window is visible, there's a spinner informing the user of what is going on, but not if it's hidden. So I think I am inclined that way. On the other hand, if there are no instances to stop, there is no point bringing the window back up...

Copy link
Author

@ghost ghost May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no need for a dialogue show, a pop-up window can be just interfering... If someone closes the app from the tray, he hardly wants to see a pop-up window without need (which will disappear itself in a couple of seconds).

Copy link
Collaborator

@ricab ricab May 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand what you mean, that pop-up is not ideal, particularly if there are no instances to stop. However, depending on how many VMs there are and what they are doing, stopping them can take a lot longer than a couple of seconds (we even had to increase the timeout to 5 minutes in the past). Until they stop, there would be no feedback and it would just feel like the tray wasn't reacting.

Copy link
Author

@ghost ghost May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with a very long delay, it would be better to show the presence of a stopping process.
May be implemented something like:

final closeJob = ref.read(guiSettingProvider(onAppCloseKey);
if (closeJob != 'nothing' &&
     (!await windowManager.isVisible() ||
      await windowManager.isMinimized())
{
          windowManager.showAndRestore();
}

switch (closeJob) { ...

or even restore only invisible:

case 'stop':
  if (!await windowManager.isVisible()) windowManager.showAndRestore();
  stopAllInstances();
default:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that, although I think we'd better drop the switch at that point. Perhaps something like, in line 169, get the setting and add || closeJob == 'nothing' to the if (and return). Then add an else to take care of stop and default cases, where the window should be restored if invisible/minimized. WDYT?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I thought about it initially, but was afraid that you would not want to get rid of switch...case. Without the switch, I can do something like this (already tried locally):

void onWindowClose() async {
  if (!await windowManager.isPreventClose()) return;
  final daemonAvailable = ref.read(daemonAvailableProvider);
  final vmsRunning =
      ref.read(vmStatusesProvider).values.contains(Status.RUNNING);
  final closeJob = ref.read(guiSettingProvider(onAppCloseKey));

  // nothing to do
  if (!daemonAvailable ||
      !vmsRunning ||
      closeJob == 'nothing') {
    windowManager.destroy();
    return;
  }

  // checking the need to restore the window
  if (!await windowManager.isVisible() ||
      await windowManager.isMinimized()) {
    windowManager.showAndRestore();
  }

  stopAllInstances() {
    final notificationsNotifier = ref.read(notificationsProvider.notifier);
    notificationsNotifier.addOperation(
      ref.read(grpcClientProvider).stop([]),
      loading: 'Stopping all instances',
      onError: (error) => 'Failed to stop all instances: $error',
      onSuccess: (_) {
        windowManager.destroy();
        return 'Stopped all instances';
      },
    );
  }

  if (closeJob == 'ask') {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => BeforeQuitDialog(
        onStop: (remember) {
          ref
              .read(guiSettingProvider(onAppCloseKey).notifier)
              .set(remember ? 'stop' : 'ask');
          stopAllInstances();
          Navigator.pop(context);
        },
        onKeep: (remember) {
          ref
              .read(guiSettingProvider(onAppCloseKey).notifier)
              .set(remember ? 'nothing' : 'ask');
          windowManager.destroy();
        },
      ),
    );
  } else {
    stopAllInstances();
  }
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that makes the most sense to me.

@ghost ghost force-pushed the t78231 branch 3 times, most recently from f5cd212 to 9c77a59 Compare May 6, 2025 16:17
@ricab
Copy link
Collaborator

ricab commented May 23, 2025

Hey @Artem-OSSRevival, would you mind rebasing this and doing a formatting pass to get it through CI? Thanks!

Previously, the tray menu action "Quit" caused a function to immediately destroy the window. Now the usual process of closing window is taking place.

Signed-off-by: Artem <artem.vlasenko@ossrevival.org>
@ghost ghost force-pushed the t78231 branch from 9c77a59 to de7ebd5 Compare May 26, 2025 13:00
@ricab ricab added this to the 1.16.0 milestone May 26, 2025
@ricab ricab requested a review from levkropp June 2, 2025 18:38
Copy link
Contributor

@levkropp levkropp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, works on 25.04 with GNOME 48 as expected!

Copy link
Collaborator

@ricab ricab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great stuff, thanks!

@ricab
Copy link
Collaborator

ricab commented Jun 3, 2025

Hi @Artem-OSSRevival, our CI is unfortunately unable to deal with external PRs properly ATM. I have opened #4134 for that, but for the time being we'll need to push your branch to our repo and make a clone of this PR. You will still retain authorship of the commits, of course, and we'll be sure to mention you in the PR that gets merged! I hope you don't mind 🙂

Thanks again for your valuable contribution!

@ghost
Copy link
Author

ghost commented Jun 3, 2025

Hi @ricab. No problems. The main thing is the prosperity of the project :)

@github-merge-queue github-merge-queue bot closed this pull request by merging all changes into canonical:main in 1da2a90 Jun 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multipass GUI does not honour question close setting when quitting from the tray
2 participants