Fix video and audio playback to pause on window close
This commit is contained in:
parent
d215e1b9be
commit
96131112da
9 changed files with 98 additions and 1 deletions
12
app/main.ts
12
app/main.ts
|
@ -832,6 +832,12 @@ async function createWindow() {
|
||||||
// App dock icon bounce
|
// App dock icon bounce
|
||||||
bounce.init(mainWindow);
|
bounce.init(mainWindow);
|
||||||
|
|
||||||
|
mainWindow.on('hide', () => {
|
||||||
|
if (mainWindow && !windowState.shouldQuit()) {
|
||||||
|
mainWindow.webContents.send('set-media-playback-disabled', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Emitted when the window is about to be closed.
|
// Emitted when the window is about to be closed.
|
||||||
// Note: We do most of our shutdown logic here because all windows are closed by
|
// Note: We do most of our shutdown logic here because all windows are closed by
|
||||||
// Electron before the app quits.
|
// Electron before the app quits.
|
||||||
|
@ -937,6 +943,12 @@ async function createWindow() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mainWindow.on('show', () => {
|
||||||
|
if (mainWindow) {
|
||||||
|
mainWindow.webContents.send('set-media-playback-disabled', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
mainWindow.once('ready-to-show', async () => {
|
mainWindow.once('ready-to-show', async () => {
|
||||||
getLogger().info('main window is ready-to-show');
|
getLogger().info('main window is ready-to-show');
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ export function AvatarLightbox({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isViewOnce
|
isViewOnce
|
||||||
media={[]}
|
media={[]}
|
||||||
|
playbackDisabled={false}
|
||||||
saveAttachment={noop}
|
saveAttachment={noop}
|
||||||
toggleForwardMessagesModal={noop}
|
toggleForwardMessagesModal={noop}
|
||||||
onMediaPlaybackStart={noop}
|
onMediaPlaybackStart={noop}
|
||||||
|
|
|
@ -66,6 +66,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
media,
|
media,
|
||||||
saveAttachment: action('saveAttachment'),
|
saveAttachment: action('saveAttachment'),
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
|
playbackDisabled: false,
|
||||||
toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
|
toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
|
||||||
onMediaPlaybackStart: noop,
|
onMediaPlaybackStart: noop,
|
||||||
onPrevAttachment: () => {
|
onPrevAttachment: () => {
|
||||||
|
|
|
@ -36,6 +36,7 @@ export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isViewOnce?: boolean;
|
isViewOnce?: boolean;
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
|
playbackDisabled: boolean;
|
||||||
saveAttachment: SaveAttachmentActionCreatorType;
|
saveAttachment: SaveAttachmentActionCreatorType;
|
||||||
selectedIndex: number;
|
selectedIndex: number;
|
||||||
toggleForwardMessagesModal: (messageIds: ReadonlyArray<string>) => unknown;
|
toggleForwardMessagesModal: (messageIds: ReadonlyArray<string>) => unknown;
|
||||||
|
@ -82,6 +83,7 @@ export function Lightbox({
|
||||||
saveAttachment,
|
saveAttachment,
|
||||||
selectedIndex,
|
selectedIndex,
|
||||||
toggleForwardMessagesModal,
|
toggleForwardMessagesModal,
|
||||||
|
playbackDisabled,
|
||||||
onMediaPlaybackStart,
|
onMediaPlaybackStart,
|
||||||
onNextAttachment,
|
onNextAttachment,
|
||||||
onPrevAttachment,
|
onPrevAttachment,
|
||||||
|
@ -250,6 +252,16 @@ export function Lightbox({
|
||||||
}
|
}
|
||||||
}, [videoElement, onMediaPlaybackStart]);
|
}, [videoElement, onMediaPlaybackStart]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!videoElement || videoElement.paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playbackDisabled) {
|
||||||
|
videoElement.pause();
|
||||||
|
}
|
||||||
|
}, [playbackDisabled, videoElement]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
document.body.appendChild(div);
|
document.body.appendChild(div);
|
||||||
|
|
|
@ -49,11 +49,14 @@ export type LightboxStateType =
|
||||||
hasPrevMessage: boolean;
|
hasPrevMessage: boolean;
|
||||||
hasNextMessage: boolean;
|
hasNextMessage: boolean;
|
||||||
selectedIndex: number | undefined;
|
selectedIndex: number | undefined;
|
||||||
|
playbackDisabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
||||||
const SHOW_LIGHTBOX = 'lightbox/SHOW';
|
const SHOW_LIGHTBOX = 'lightbox/SHOW';
|
||||||
const SET_SELECTED_LIGHTBOX_INDEX = 'lightbox/SET_SELECTED_LIGHTBOX_INDEX';
|
const SET_SELECTED_LIGHTBOX_INDEX = 'lightbox/SET_SELECTED_LIGHTBOX_INDEX';
|
||||||
|
const SET_LIGHTBOX_PLAYBACK_DISABLED =
|
||||||
|
'lightbox/SET_LIGHTBOX_PLAYBACK_DISABLED';
|
||||||
|
|
||||||
type CloseLightboxActionType = ReadonlyDeep<{
|
type CloseLightboxActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_LIGHTBOX;
|
type: typeof CLOSE_LIGHTBOX;
|
||||||
|
@ -71,6 +74,11 @@ type ShowLightboxActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type SetLightboxPlaybackDisabledActionType = ReadonlyDeep<{
|
||||||
|
type: typeof SET_LIGHTBOX_PLAYBACK_DISABLED;
|
||||||
|
payload: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
type SetSelectedLightboxIndexActionType = ReadonlyDeep<{
|
type SetSelectedLightboxIndexActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_SELECTED_LIGHTBOX_INDEX;
|
type: typeof SET_SELECTED_LIGHTBOX_INDEX;
|
||||||
payload: number;
|
payload: number;
|
||||||
|
@ -83,7 +91,8 @@ type LightboxActionType =
|
||||||
| MessageDeletedActionType
|
| MessageDeletedActionType
|
||||||
| MessageExpiredActionType
|
| MessageExpiredActionType
|
||||||
| ShowLightboxActionType
|
| ShowLightboxActionType
|
||||||
| SetSelectedLightboxIndexActionType;
|
| SetSelectedLightboxIndexActionType
|
||||||
|
| SetLightboxPlaybackDisabledActionType;
|
||||||
|
|
||||||
function closeLightbox(): ThunkAction<
|
function closeLightbox(): ThunkAction<
|
||||||
void,
|
void,
|
||||||
|
@ -115,6 +124,28 @@ function closeLightbox(): ThunkAction<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPlaybackDisabled(
|
||||||
|
playbackDisabled: boolean
|
||||||
|
): ThunkAction<
|
||||||
|
void,
|
||||||
|
RootStateType,
|
||||||
|
unknown,
|
||||||
|
SetLightboxPlaybackDisabledActionType
|
||||||
|
> {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const { lightbox } = getState();
|
||||||
|
|
||||||
|
if (!lightbox.isShowingLightbox) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: SET_LIGHTBOX_PLAYBACK_DISABLED,
|
||||||
|
payload: playbackDisabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function showLightboxWithMedia(
|
function showLightboxWithMedia(
|
||||||
selectedIndex: number | undefined,
|
selectedIndex: number | undefined,
|
||||||
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
|
@ -340,6 +371,7 @@ function showLightbox(opts: {
|
||||||
older.length > 0 && filterValidAttachments(older[0]).length > 0,
|
older.length > 0 && filterValidAttachments(older[0]).length > 0,
|
||||||
hasNextMessage:
|
hasNextMessage:
|
||||||
newer.length > 0 && filterValidAttachments(newer[0]).length > 0,
|
newer.length > 0 && filterValidAttachments(newer[0]).length > 0,
|
||||||
|
playbackDisabled: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -481,6 +513,7 @@ export const actions = {
|
||||||
showLightboxForPrevMessage,
|
showLightboxForPrevMessage,
|
||||||
showLightboxForNextMessage,
|
showLightboxForNextMessage,
|
||||||
setSelectedLightboxIndex,
|
setSelectedLightboxIndex,
|
||||||
|
setPlaybackDisabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useLightboxActions = (): BoundActionCreatorsMapObject<
|
export const useLightboxActions = (): BoundActionCreatorsMapObject<
|
||||||
|
@ -505,6 +538,7 @@ export function reducer(
|
||||||
return {
|
return {
|
||||||
...action.payload,
|
...action.payload,
|
||||||
isShowingLightbox: true,
|
isShowingLightbox: true,
|
||||||
|
playbackDisabled: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,6 +556,17 @@ export function reducer(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action.type === SET_LIGHTBOX_PLAYBACK_DISABLED) {
|
||||||
|
if (!state.isShowingLightbox) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
playbackDisabled: action.payload,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
action.type === MESSAGE_CHANGED ||
|
action.type === MESSAGE_CHANGED ||
|
||||||
action.type === MESSAGE_DELETED ||
|
action.type === MESSAGE_DELETED ||
|
||||||
|
|
|
@ -46,3 +46,8 @@ export const getHasNextMessage = createSelector(
|
||||||
getLightboxState,
|
getLightboxState,
|
||||||
(state): boolean => state.isShowingLightbox && state.hasNextMessage
|
(state): boolean => state.isShowingLightbox && state.hasNextMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getPlaybackDisabled = createSelector(
|
||||||
|
getLightboxState,
|
||||||
|
(state): boolean => state.isShowingLightbox && state.playbackDisabled
|
||||||
|
);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
getMedia,
|
getMedia,
|
||||||
getHasPrevMessage,
|
getHasPrevMessage,
|
||||||
getHasNextMessage,
|
getHasNextMessage,
|
||||||
|
getPlaybackDisabled,
|
||||||
getSelectedIndex,
|
getSelectedIndex,
|
||||||
shouldShowLightbox,
|
shouldShowLightbox,
|
||||||
} from '../selectors/lightbox';
|
} from '../selectors/lightbox';
|
||||||
|
@ -50,6 +51,7 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
const hasPrevMessage = useSelector<StateType, boolean>(getHasPrevMessage);
|
const hasPrevMessage = useSelector<StateType, boolean>(getHasPrevMessage);
|
||||||
const hasNextMessage = useSelector<StateType, boolean>(getHasNextMessage);
|
const hasNextMessage = useSelector<StateType, boolean>(getHasNextMessage);
|
||||||
const selectedIndex = useSelector<StateType, number>(getSelectedIndex);
|
const selectedIndex = useSelector<StateType, number>(getSelectedIndex);
|
||||||
|
const playbackDisabled = useSelector<StateType, boolean>(getPlaybackDisabled);
|
||||||
|
|
||||||
const onPrevAttachment = useCallback(() => {
|
const onPrevAttachment = useCallback(() => {
|
||||||
if (selectedIndex <= 0) {
|
if (selectedIndex <= 0) {
|
||||||
|
@ -93,6 +95,7 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isViewOnce={isViewOnce}
|
isViewOnce={isViewOnce}
|
||||||
media={media}
|
media={media}
|
||||||
|
playbackDisabled={playbackDisabled}
|
||||||
saveAttachment={saveAttachment}
|
saveAttachment={saveAttachment}
|
||||||
selectedIndex={selectedIndex || 0}
|
selectedIndex={selectedIndex || 0}
|
||||||
toggleForwardMessagesModal={toggleForwardMessagesModal}
|
toggleForwardMessagesModal={toggleForwardMessagesModal}
|
||||||
|
|
|
@ -119,6 +119,7 @@ export type IPCEventsCallbacksType = {
|
||||||
removeDarkOverlay: () => void;
|
removeDarkOverlay: () => void;
|
||||||
resetAllChatColors: () => void;
|
resetAllChatColors: () => void;
|
||||||
resetDefaultChatColor: () => void;
|
resetDefaultChatColor: () => void;
|
||||||
|
setMediaPlaybackDisabled: (playbackDisabled: boolean) => void;
|
||||||
showConversationViaNotification: (data: NotificationClickData) => void;
|
showConversationViaNotification: (data: NotificationClickData) => void;
|
||||||
showConversationViaSignalDotMe: (
|
showConversationViaSignalDotMe: (
|
||||||
kind: string,
|
kind: string,
|
||||||
|
@ -640,6 +641,13 @@ export function createIPCEvents(
|
||||||
getMediaPermissions: window.IPC.getMediaPermissions,
|
getMediaPermissions: window.IPC.getMediaPermissions,
|
||||||
getMediaCameraPermissions: window.IPC.getMediaCameraPermissions,
|
getMediaCameraPermissions: window.IPC.getMediaCameraPermissions,
|
||||||
|
|
||||||
|
setMediaPlaybackDisabled: (playbackDisabled: boolean) => {
|
||||||
|
window.reduxActions.lightbox.setPlaybackDisabled(playbackDisabled);
|
||||||
|
if (playbackDisabled) {
|
||||||
|
window.reduxActions.audioPlayer.pauseVoiceNotePlayer();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
...overrideEvents,
|
...overrideEvents,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,16 @@ ipc.on('power-channel:lock-screen', () => {
|
||||||
window.Whisper.events.trigger('powerMonitorLockScreen');
|
window.Whisper.events.trigger('powerMonitorLockScreen');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipc.on(
|
||||||
|
'set-media-playback-disabled',
|
||||||
|
(_event: unknown, playbackDisabled: unknown) => {
|
||||||
|
const { setMediaPlaybackDisabled } = window.Events || {};
|
||||||
|
if (setMediaPlaybackDisabled) {
|
||||||
|
setMediaPlaybackDisabled(Boolean(playbackDisabled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ipc.on('window:set-window-stats', (_event, stats) => {
|
ipc.on('window:set-window-stats', (_event, stats) => {
|
||||||
if (!window.reduxActions) {
|
if (!window.reduxActions) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue