Ask for confirmation when closing app during call
This commit is contained in:
parent
c772f2abc5
commit
93c019dc30
4 changed files with 129 additions and 0 deletions
|
@ -5723,6 +5723,14 @@
|
|||
"messageformat": "Would you like to discard these changes?",
|
||||
"description": "ConfirmationDialog text for discarding changes"
|
||||
},
|
||||
"icu:ConfirmationDialog__Title--in-call-close-requested": {
|
||||
"messageformat": "Close Signal and end the call?",
|
||||
"description": "ConfirmationDialog title when trying to close the app while in a call."
|
||||
},
|
||||
"icu:ConfirmationDialog__Title--close-requested-not-now": {
|
||||
"messageformat": "Not Now",
|
||||
"description": "Confirmation dialog button to cancel closing the app, while in a call and trying to close the app."
|
||||
},
|
||||
"icu:ProfileEditor--edit-photo": {
|
||||
"messageformat": "Edit photo",
|
||||
"description": "Text of a button on profile editor that leads to the avatar editor"
|
||||
|
|
68
app/main.ts
68
app/main.ts
|
@ -862,6 +862,21 @@ async function createWindow() {
|
|||
// Prevent the shutdown
|
||||
e.preventDefault();
|
||||
|
||||
// In certain cases such as during an active call, we ask the user to confirm close
|
||||
// which includes shutdown, clicking X on MacOS or closing to tray.
|
||||
let shouldClose = true;
|
||||
try {
|
||||
shouldClose = await maybeRequestCloseConfirmation();
|
||||
} catch (error) {
|
||||
getLogger().warn(
|
||||
'Error while requesting close confirmation.',
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
}
|
||||
if (!shouldClose) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* if the user is in fullscreen mode and closes the window, not the
|
||||
* application, we need them leave fullscreen first before closing it to
|
||||
|
@ -2057,6 +2072,59 @@ function setupMenu(options?: Partial<CreateTemplateOptionsType>) {
|
|||
});
|
||||
}
|
||||
|
||||
async function maybeRequestCloseConfirmation(): Promise<boolean> {
|
||||
if (!mainWindow || !mainWindow.webContents) {
|
||||
return true;
|
||||
}
|
||||
|
||||
getLogger().info(
|
||||
'maybeRequestCloseConfirmation: Checking to see if close confirmation is needed'
|
||||
);
|
||||
const request = new Promise<boolean>(resolveFn => {
|
||||
let timeout: NodeJS.Timeout | undefined;
|
||||
|
||||
if (!mainWindow) {
|
||||
resolveFn(true);
|
||||
return;
|
||||
}
|
||||
|
||||
ipc.once('received-close-confirmation', (_event, result) => {
|
||||
getLogger().info('maybeRequestCloseConfirmation: Response received');
|
||||
|
||||
clearTimeoutIfNecessary(timeout);
|
||||
resolveFn(result);
|
||||
});
|
||||
|
||||
ipc.once('requested-close-confirmation', () => {
|
||||
getLogger().info(
|
||||
'maybeRequestCloseConfirmation: Confirmation dialog shown, waiting for user.'
|
||||
);
|
||||
clearTimeoutIfNecessary(timeout);
|
||||
});
|
||||
|
||||
mainWindow.webContents.send('maybe-request-close-confirmation');
|
||||
|
||||
// Wait a short time then proceed. Normally the dialog should be
|
||||
// shown right away.
|
||||
timeout = setTimeout(() => {
|
||||
getLogger().error(
|
||||
'maybeRequestCloseConfirmation: Response never received; continuing with close.'
|
||||
);
|
||||
resolveFn(true);
|
||||
}, 10 * 1000);
|
||||
});
|
||||
|
||||
try {
|
||||
return await request;
|
||||
} catch (error) {
|
||||
getLogger().error(
|
||||
'maybeRequestCloseConfirmation error:',
|
||||
Errors.toLogFormat(error)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function requestShutdown() {
|
||||
if (!mainWindow || !mainWindow.webContents) {
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,7 @@ import type { AuthorizeArtCreatorDataType } from '../state/ducks/globalModals';
|
|||
import { calling } from '../services/calling';
|
||||
import { resolveUsernameByLinkBase64 } from '../services/username';
|
||||
import { writeProfile } from '../services/writeProfile';
|
||||
import { isInCall as getIsInCall } from '../state/selectors/calling';
|
||||
import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations';
|
||||
import { getCustomColors } from '../state/selectors/items';
|
||||
import { themeChanged } from '../shims/themeChanged';
|
||||
|
@ -43,6 +44,7 @@ import { isValidE164 } from './isValidE164';
|
|||
import { fromWebSafeBase64 } from './webSafeBase64';
|
||||
import { getConversation } from './getConversation';
|
||||
import { instance, PhoneNumberFormat } from './libphonenumberInstance';
|
||||
import { showConfirmationDialog } from './showConfirmationDialog';
|
||||
|
||||
type SentMediaQualityType = 'standard' | 'high';
|
||||
type ThemeType = 'light' | 'dark' | 'system';
|
||||
|
@ -129,6 +131,7 @@ export type IPCEventsCallbacksType = {
|
|||
showGroupViaLink: (value: string) => Promise<void>;
|
||||
showReleaseNotes: () => void;
|
||||
showStickerPack: (packId: string, key: string) => void;
|
||||
maybeRequestCloseConfirmation: () => Promise<boolean>;
|
||||
shutdown: () => Promise<void>;
|
||||
unknownSignalLink: () => void;
|
||||
getCustomColors: () => Record<string, CustomColorType>;
|
||||
|
@ -620,6 +623,43 @@ export function createIPCEvents(
|
|||
showUnknownSgnlLinkModal();
|
||||
},
|
||||
|
||||
maybeRequestCloseConfirmation: async (): Promise<boolean> => {
|
||||
const isInCall = getIsInCall(window.reduxStore.getState());
|
||||
if (!isInCall) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
showConfirmationDialog({
|
||||
dialogName: 'closeConfirmation',
|
||||
onTopOfEverything: true,
|
||||
cancelText: window.i18n(
|
||||
'icu:ConfirmationDialog__Title--close-requested-not-now'
|
||||
),
|
||||
confirmStyle: 'negative',
|
||||
title: window.i18n(
|
||||
'icu:ConfirmationDialog__Title--in-call-close-requested'
|
||||
),
|
||||
okText: window.i18n('icu:close'),
|
||||
reject: () => reject(),
|
||||
resolve: () => resolve(),
|
||||
});
|
||||
});
|
||||
log.info('Close confirmed by user.');
|
||||
if (isInCall) {
|
||||
window.reduxActions.calling.hangUpActiveCall(
|
||||
'User confirmed in-call close.'
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch {
|
||||
log.info('Close cancelled by user.');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
unknownSignalLink: () => {
|
||||
log.warn('unknownSignalLink: Showing error dialog');
|
||||
showUnknownSgnlLinkModal();
|
||||
|
|
|
@ -388,6 +388,19 @@ ipc.on('get-ready-for-shutdown', async () => {
|
|||
}
|
||||
});
|
||||
|
||||
ipc.on('maybe-request-close-confirmation', async () => {
|
||||
const { maybeRequestCloseConfirmation } = window.Events;
|
||||
if (!maybeRequestCloseConfirmation) {
|
||||
ipc.send('received-close-confirmation', true);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info('Requesting close confirmation.');
|
||||
ipc.send('requested-close-confirmation');
|
||||
const result = await maybeRequestCloseConfirmation();
|
||||
ipc.send('received-close-confirmation', result);
|
||||
});
|
||||
|
||||
ipc.on('show-release-notes', () => {
|
||||
const { showReleaseNotes } = window.Events;
|
||||
if (showReleaseNotes) {
|
||||
|
|
Loading…
Reference in a new issue