Audio Player: Fix resuming playback (#6542)
This commit is contained in:
parent
61ec53ac2b
commit
9a9e8d03aa
@ -10,6 +10,7 @@ import type { IconName } from '../../../types/icons';
|
||||
|
||||
import { PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION } from '../../../config';
|
||||
import {
|
||||
getMediaFormat,
|
||||
getMessageContent, isMessageLocal,
|
||||
} from '../../../global/helpers';
|
||||
import { getPeerTitle } from '../../../global/helpers/peers';
|
||||
@ -20,7 +21,6 @@ import { selectMessageMediaDuration } from '../../../global/selectors/media';
|
||||
import { makeTrackId } from '../../../util/audioPlayer';
|
||||
import { IS_IOS, IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import * as mediaLoader from '../../../util/mediaLoader';
|
||||
import { clearMediaSession } from '../../../util/mediaSession';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
|
||||
@ -30,6 +30,7 @@ import useAudioPlayer from '../../../hooks/useAudioPlayer';
|
||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useMedia from '../../../hooks/useMedia';
|
||||
import useMessageMediaMetadata from '../../../hooks/useMessageMediaMetadata';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
import useShowTransition from '../../../hooks/useShowTransition';
|
||||
@ -109,8 +110,10 @@ const AudioPlayer: FC<OwnProps & StateProps> = ({
|
||||
const shouldRenderPlaybackButton = isVoice || (audio?.duration || 0) > PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION;
|
||||
const senderName = sender ? getPeerTitle(lang, sender) : undefined;
|
||||
|
||||
const playableMedia = voice || video || audio;
|
||||
const mediaHash = useMessageMediaHash(renderingMessage, 'inline');
|
||||
const mediaData = mediaHash && mediaLoader.getFromMemory(mediaHash);
|
||||
const mediaFormat = playableMedia && getMediaFormat(playableMedia, 'inline');
|
||||
const mediaData = useMedia(mediaHash, false, mediaFormat);
|
||||
const mediaMetadata = useMessageMediaMetadata(renderingMessage, sender, chat);
|
||||
|
||||
const {
|
||||
@ -424,8 +427,9 @@ export default withGlobal<OwnProps>(
|
||||
const sender = message && selectSender(global, message);
|
||||
const chat = message && selectChat(global, message.chatId);
|
||||
const {
|
||||
volume, playbackRate, isMuted, isPlaybackRateActive, timestamp,
|
||||
playbackRate, isMuted, isPlaybackRateActive, timestamp,
|
||||
} = selectTabState(global).audioPlayer;
|
||||
const { volume } = global.audioPlayer;
|
||||
|
||||
const mediaDuration = message ? selectMessageMediaDuration(global, message) : undefined;
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ addActionHandler('replyToNextMessage', (global, actions, payload): ActionReturnT
|
||||
|
||||
addActionHandler('openAudioPlayer', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
chatId, threadId, messageId, origin, volume, playbackRate, isMuted, timestamp,
|
||||
chatId, threadId, messageId, origin, playbackRate, isMuted, timestamp,
|
||||
tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
@ -195,7 +195,6 @@ addActionHandler('openAudioPlayer', (global, actions, payload): ActionReturnType
|
||||
messageId,
|
||||
timestamp,
|
||||
origin: origin ?? tabState.audioPlayer.origin,
|
||||
volume: volume ?? tabState.audioPlayer.volume,
|
||||
playbackRate: playbackRate || tabState.audioPlayer.playbackRate || global.audioPlayer.lastPlaybackRate,
|
||||
isPlaybackRateActive: (tabState.audioPlayer.isPlaybackRateActive === undefined
|
||||
? global.audioPlayer.isLastPlaybackRateActive
|
||||
@ -210,13 +209,20 @@ addActionHandler('setAudioPlayerVolume', (global, actions, payload): ActionRetur
|
||||
volume, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
return updateTabState(global, {
|
||||
global = updateTabState(global, {
|
||||
audioPlayer: {
|
||||
...selectTabState(global, tabId).audioPlayer,
|
||||
volume,
|
||||
isMuted: false,
|
||||
},
|
||||
}, tabId);
|
||||
global = {
|
||||
...global,
|
||||
audioPlayer: {
|
||||
...global.audioPlayer,
|
||||
volume,
|
||||
},
|
||||
};
|
||||
return global;
|
||||
});
|
||||
|
||||
addActionHandler('setAudioPlayerPlaybackRate', (global, actions, payload): ActionReturnType => {
|
||||
@ -273,7 +279,6 @@ addActionHandler('closeAudioPlayer', (global, actions, payload): ActionReturnTyp
|
||||
const tabState = selectTabState(global, tabId);
|
||||
return updateTabState(global, {
|
||||
audioPlayer: {
|
||||
volume: tabState.audioPlayer.volume,
|
||||
playbackRate: tabState.audioPlayer.playbackRate,
|
||||
isPlaybackRateActive: tabState.audioPlayer.isPlaybackRateActive,
|
||||
isMuted: tabState.audioPlayer.isMuted,
|
||||
|
||||
@ -367,6 +367,10 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
|
||||
cached.auth = initialState.auth;
|
||||
cached.auth.rememberMe = untypedCached.rememberMe;
|
||||
}
|
||||
|
||||
if (cached.audioPlayer.volume === undefined) {
|
||||
cached.audioPlayer.volume = initialState.audioPlayer.volume;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCache(force?: boolean) {
|
||||
|
||||
@ -106,6 +106,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
||||
appConfig: DEFAULT_APP_CONFIG,
|
||||
|
||||
audioPlayer: {
|
||||
volume: DEFAULT_VOLUME,
|
||||
lastPlaybackRate: DEFAULT_PLAYBACK_RATE,
|
||||
},
|
||||
|
||||
@ -426,7 +427,6 @@ export const INITIAL_TAB_STATE: TabState = {
|
||||
},
|
||||
|
||||
audioPlayer: {
|
||||
volume: DEFAULT_VOLUME,
|
||||
playbackRate: DEFAULT_PLAYBACK_RATE,
|
||||
isMuted: false,
|
||||
},
|
||||
|
||||
@ -105,6 +105,7 @@ export type GlobalState = {
|
||||
botFreezeAppealId?: string;
|
||||
|
||||
audioPlayer: {
|
||||
volume: number;
|
||||
lastPlaybackRate: number;
|
||||
isLastPlaybackRateActive?: boolean;
|
||||
};
|
||||
|
||||
@ -378,7 +378,6 @@ export type TabState = {
|
||||
messageId?: number;
|
||||
threadId?: ThreadId;
|
||||
origin?: AudioOrigin;
|
||||
volume: number;
|
||||
playbackRate: number;
|
||||
isPlaybackRateActive?: boolean;
|
||||
timestamp?: number;
|
||||
|
||||
@ -65,17 +65,21 @@ const useAudioPlayer = (
|
||||
const {
|
||||
setVolume, setPlaybackRate, toggleMuted, proxy,
|
||||
} = controllerRef.current!;
|
||||
const global = getGlobal();
|
||||
|
||||
setIsPlaying(true);
|
||||
if (trackType !== 'oneTimeVoice') {
|
||||
registerMediaSession(metadata, makeMediaHandlers(controllerRef));
|
||||
}
|
||||
setPlaybackState('playing');
|
||||
const { audioPlayer } = selectTabState(getGlobal());
|
||||
setVolume(audioPlayer.volume);
|
||||
toggleMuted(Boolean(audioPlayer.isMuted));
|
||||
|
||||
const { audioPlayer: tabAudioPlayerState } = selectTabState(global);
|
||||
const { audioPlayer: globalAudioPlayerState } = global;
|
||||
setVolume(globalAudioPlayerState.volume);
|
||||
toggleMuted(Boolean(tabAudioPlayerState.isMuted));
|
||||
const duration = proxy.duration && Number.isFinite(proxy.duration) ? proxy.duration : originalDuration;
|
||||
if (trackType === 'voice' || duration > PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION) {
|
||||
setPlaybackRate(audioPlayer.playbackRate);
|
||||
setPlaybackRate(tabAudioPlayerState.playbackRate);
|
||||
}
|
||||
setPositionState({
|
||||
duration: proxy.duration || 0,
|
||||
|
||||
@ -4,7 +4,6 @@ import type { ApiMessage } from '../api/types';
|
||||
import type { MessageKey } from './keys/messageKey';
|
||||
import { AudioOrigin, GlobalSearchContent } from '../types';
|
||||
|
||||
import { requestNextMutation } from '../lib/fasterdom/fasterdom';
|
||||
import { selectCurrentMessageList, selectTabState } from '../global/selectors';
|
||||
import { IS_SAFARI } from './browser/windowEnvironment';
|
||||
import { getMessageServerKey, parseMessageKey } from './keys/messageKey';
|
||||
@ -179,14 +178,15 @@ export function register(
|
||||
|
||||
stop() {
|
||||
if (currentTrackId === trackId) {
|
||||
// Hack, reset `src` to remove default media session notification
|
||||
const prevSrc = audio.src;
|
||||
audio.pause();
|
||||
// `onPause` not called otherwise, but required to sync UI
|
||||
requestNextMutation(() => {
|
||||
|
||||
// `onPause` is required to reset UI state
|
||||
audio.addEventListener('pause', () => {
|
||||
// Hack, reset `src` to remove default media session notification
|
||||
audio.src = '';
|
||||
audio.src = prevSrc;
|
||||
});
|
||||
}, { once: true });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user