mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Disable consecutive audio playback in Media Gallery
This commit is contained in:
@@ -62,7 +62,7 @@ const MESSAGE_DEFAULT_PROPS = {
|
|||||||
endPoll: shouldNeverBeCalled,
|
endPoll: shouldNeverBeCalled,
|
||||||
pushPanelForConversation: shouldNeverBeCalled,
|
pushPanelForConversation: shouldNeverBeCalled,
|
||||||
renderAudioAttachment: () => <div />,
|
renderAudioAttachment: () => <div />,
|
||||||
renderingContext: 'EditHistoryMessagesModal',
|
renderingContext: 'EditHistoryMessagesModal' as const,
|
||||||
saveAttachment: shouldNeverBeCalled,
|
saveAttachment: shouldNeverBeCalled,
|
||||||
saveAttachments: shouldNeverBeCalled,
|
saveAttachments: shouldNeverBeCalled,
|
||||||
scrollToQuotedMessage: shouldNeverBeCalled,
|
scrollToQuotedMessage: shouldNeverBeCalled,
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import type {
|
|||||||
} from './ReactionViewer.dom.js';
|
} from './ReactionViewer.dom.js';
|
||||||
import { ReactionViewer } from './ReactionViewer.dom.js';
|
import { ReactionViewer } from './ReactionViewer.dom.js';
|
||||||
import { LinkPreviewDate } from './LinkPreviewDate.dom.js';
|
import { LinkPreviewDate } from './LinkPreviewDate.dom.js';
|
||||||
|
import type { RenderingContextType } from '../../types/RenderingContext.d.ts';
|
||||||
import type { LinkPreviewForUIType } from '../../types/message/LinkPreviews.std.js';
|
import type { LinkPreviewForUIType } from '../../types/message/LinkPreviews.std.js';
|
||||||
import type { MessageStatusType } from '../../types/message/MessageStatus.std.js';
|
import type { MessageStatusType } from '../../types/message/MessageStatus.std.js';
|
||||||
import { shouldUseFullSizeLinkPreviewImage } from '../../linkPreviews/shouldUseFullSizeLinkPreviewImage.std.js';
|
import { shouldUseFullSizeLinkPreviewImage } from '../../linkPreviews/shouldUseFullSizeLinkPreviewImage.std.js';
|
||||||
@@ -178,7 +179,7 @@ export enum MessageInteractivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type AudioAttachmentProps = {
|
export type AudioAttachmentProps = {
|
||||||
renderingContext: string;
|
renderingContext: RenderingContextType;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
buttonRef: React.RefObject<HTMLButtonElement>;
|
buttonRef: React.RefObject<HTMLButtonElement>;
|
||||||
theme: ThemeType | undefined;
|
theme: ThemeType | undefined;
|
||||||
@@ -239,7 +240,7 @@ function ReactionEmoji(props: { emojiVariantValue: string }) {
|
|||||||
|
|
||||||
export type PropsData = {
|
export type PropsData = {
|
||||||
id: string;
|
id: string;
|
||||||
renderingContext: string;
|
renderingContext: RenderingContextType;
|
||||||
contactNameColor?: ContactNameColorType;
|
contactNameColor?: ContactNameColorType;
|
||||||
conversationColor: ConversationColorType;
|
conversationColor: ConversationColorType;
|
||||||
conversationTitle: string;
|
conversationTitle: string;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { isAudio } from '../../util/Attachment.std.js';
|
|||||||
import { getLocalAttachmentUrl } from '../../util/getLocalAttachmentUrl.std.js';
|
import { getLocalAttachmentUrl } from '../../util/getLocalAttachmentUrl.std.js';
|
||||||
import { assertDev } from '../../util/assert.std.js';
|
import { assertDev } from '../../util/assert.std.js';
|
||||||
import { drop } from '../../util/drop.std.js';
|
import { drop } from '../../util/drop.std.js';
|
||||||
|
import type { RenderingContextType } from '../../types/RenderingContext.d.ts';
|
||||||
import { Sound, SoundType } from '../../util/Sound.std.js';
|
import { Sound, SoundType } from '../../util/Sound.std.js';
|
||||||
import { DataReader } from '../../sql/Client.preload.js';
|
import { DataReader } from '../../sql/Client.preload.js';
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ type AudioPlayerContentDraft = ReadonlyDeep<{
|
|||||||
/** A voice note consecutive playback */
|
/** A voice note consecutive playback */
|
||||||
export type AudioPlayerContentVoiceNote = ReadonlyDeep<{
|
export type AudioPlayerContentVoiceNote = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
context: string;
|
context: RenderingContextType;
|
||||||
current: VoiceNoteForPlayback;
|
current: VoiceNoteForPlayback;
|
||||||
// playing because it followed a message
|
// playing because it followed a message
|
||||||
// false on the first of a consecutive group
|
// false on the first of a consecutive group
|
||||||
@@ -214,6 +215,14 @@ function messageAudioEnded(): ThunkAction<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No consecutive playback in All Media view
|
||||||
|
if (content.context === 'AllMedia') {
|
||||||
|
dispatch({
|
||||||
|
type: 'audioPlayer/MESSAGE_AUDIO_ENDED',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { conversationId, context, current } = content;
|
const { conversationId, context, current } = content;
|
||||||
|
|
||||||
const next = await getNextVoiceNote({
|
const next = await getNextVoiceNote({
|
||||||
@@ -314,7 +323,7 @@ function loadVoiceNoteAudio({
|
|||||||
}: {
|
}: {
|
||||||
voiceNoteData: VoiceNoteAndConsecutiveForPlayback;
|
voiceNoteData: VoiceNoteAndConsecutiveForPlayback;
|
||||||
position: number;
|
position: number;
|
||||||
context: string;
|
context: RenderingContextType;
|
||||||
playbackRate: number;
|
playbackRate: number;
|
||||||
}): SetMessageAudioAction {
|
}): SetMessageAudioAction {
|
||||||
const { conversationId, voiceNote } = voiceNoteData;
|
const { conversationId, voiceNote } = voiceNoteData;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import React, { memo, useCallback } from 'react';
|
import React, { memo, useCallback } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import type { RenderingContextType } from '../../types/RenderingContext.d.ts';
|
||||||
import { MessageAudio } from '../../components/conversation/MessageAudio.dom.js';
|
import { MessageAudio } from '../../components/conversation/MessageAudio.dom.js';
|
||||||
import type { OwnProps as MessageAudioOwnProps } from '../../components/conversation/MessageAudio.dom.js';
|
import type { OwnProps as MessageAudioOwnProps } from '../../components/conversation/MessageAudio.dom.js';
|
||||||
import type { ActiveAudioPlayerStateType } from '../ducks/audioPlayer.preload.js';
|
import type { ActiveAudioPlayerStateType } from '../ducks/audioPlayer.preload.js';
|
||||||
@@ -24,7 +25,7 @@ import {
|
|||||||
const log = createLogger('MessageAudio');
|
const log = createLogger('MessageAudio');
|
||||||
|
|
||||||
export type Props = Omit<MessageAudioOwnProps, 'active' | 'onPlayMessage'> & {
|
export type Props = Omit<MessageAudioOwnProps, 'active' | 'onPlayMessage'> & {
|
||||||
renderingContext: string;
|
renderingContext: RenderingContextType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SmartMessageAudio = memo(function SmartMessageAudio({
|
export const SmartMessageAudio = memo(function SmartMessageAudio({
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ describe('state/selectors/audioPlayer', () => {
|
|||||||
actions.loadVoiceNoteAudio({
|
actions.loadVoiceNoteAudio({
|
||||||
voiceNoteData: voiceNoteDataForMessage('id'),
|
voiceNoteData: voiceNoteDataForMessage('id'),
|
||||||
position: 0,
|
position: 0,
|
||||||
context: 'context',
|
context: 'AllMedia',
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ describe('both/state/ducks/audioPlayer', () => {
|
|||||||
actions.loadVoiceNoteAudio({
|
actions.loadVoiceNoteAudio({
|
||||||
voiceNoteData: voiceNoteDataForMessage(MESSAGE_ID),
|
voiceNoteData: voiceNoteDataForMessage(MESSAGE_ID),
|
||||||
position: 0,
|
position: 0,
|
||||||
context: 'context',
|
context: 'AllMedia',
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -65,7 +65,7 @@ describe('both/state/ducks/audioPlayer', () => {
|
|||||||
|
|
||||||
if (content && AudioPlayerContent.isVoiceNote(content)) {
|
if (content && AudioPlayerContent.isVoiceNote(content)) {
|
||||||
assert.strictEqual(content.current.id, MESSAGE_ID);
|
assert.strictEqual(content.current.id, MESSAGE_ID);
|
||||||
assert.strictEqual(content.context, 'context');
|
assert.strictEqual(content.context, 'AllMedia');
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
@@ -81,7 +81,7 @@ describe('both/state/ducks/audioPlayer', () => {
|
|||||||
actions.loadVoiceNoteAudio({
|
actions.loadVoiceNoteAudio({
|
||||||
voiceNoteData: voiceNoteDataForMessage('test'),
|
voiceNoteData: voiceNoteDataForMessage('test'),
|
||||||
position: 0,
|
position: 0,
|
||||||
context: 'context',
|
context: 'AllMedia',
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -91,7 +91,7 @@ describe('both/state/ducks/audioPlayer', () => {
|
|||||||
|
|
||||||
if (content && AudioPlayerContent.isVoiceNote(content)) {
|
if (content && AudioPlayerContent.isVoiceNote(content)) {
|
||||||
assert.strictEqual(content.current.id, 'test');
|
assert.strictEqual(content.current.id, 'test');
|
||||||
assert.strictEqual(content.context, 'context');
|
assert.strictEqual(content.context, 'AllMedia');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
10
ts/types/RenderingContext.d.ts
vendored
Normal file
10
ts/types/RenderingContext.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
export type RenderingContextType =
|
||||||
|
| 'EditHistoryMessagesModal'
|
||||||
|
| 'StoryViewsNRepliesModal'
|
||||||
|
| 'conversation/MessageDetail'
|
||||||
|
| 'conversation/TimelineItem'
|
||||||
|
| 'AllMedia'
|
||||||
|
| 'storybook';
|
||||||
Reference in New Issue
Block a user