diff --git a/ts/components/MiniPlayer.tsx b/ts/components/MiniPlayer.tsx
index 49ad6c0423..c31cbf42a2 100644
--- a/ts/components/MiniPlayer.tsx
+++ b/ts/components/MiniPlayer.tsx
@@ -8,6 +8,7 @@ import { durationToPlaybackText } from '../util/durationToPlaybackText';
import { PlaybackButton } from './PlaybackButton';
import { PlaybackRateButton } from './PlaybackRateButton';
import { UserText } from './UserText';
+import { shortenFileName } from '../util/attachments';
export enum PlayerState {
loading = 'loading',
@@ -18,6 +19,7 @@ export enum PlayerState {
export type Props = Readonly<{
i18n: LocalizerType;
title: string;
+ fileName: string | undefined
currentTime: number;
// not available until audio has loaded
duration: number | undefined;
@@ -34,6 +36,7 @@ export type Props = Readonly<{
export function MiniPlayer({
i18n,
title,
+ fileName,
state,
currentTime,
duration,
@@ -100,8 +103,9 @@ export function MiniPlayer({
·
+ {shortenFileName(fileName, true)}
{duration !== undefined && (
-
+
{durationToPlaybackText(
state === PlayerState.loading ? duration : currentTime
)}
diff --git a/ts/components/conversation/MessageAudio.tsx b/ts/components/conversation/MessageAudio.tsx
index 4f6abcb63a..396bf65518 100644
--- a/ts/components/conversation/MessageAudio.tsx
+++ b/ts/components/conversation/MessageAudio.tsx
@@ -23,6 +23,7 @@ import { WaveformScrubber } from './WaveformScrubber';
import { useComputePeaks } from '../../hooks/useComputePeaks';
import { durationToPlaybackText } from '../../util/durationToPlaybackText';
import { shouldNeverBeCalled } from '../../util/shouldNeverBeCalled';
+import { shortenFileName } from '../../util/attachments';
export type OwnProps = Readonly<{
active:
@@ -167,7 +168,7 @@ export function MessageAudio(props: Props): JSX.Element {
const [isPlayedDotVisible, setIsPlayedDotVisible] = React.useState(!played);
const audioUrl = isDownloaded(attachment) ? attachment.url : undefined;
-
+ const fileName = (attachment.fileName && !attachment.isVoiceMessage) ? shortenFileName(attachment.fileName) : undefined;
const { duration, hasPeaks, peaks } = useComputePeaks({
audioUrl,
activeDuration: active?.duration,
@@ -369,7 +370,6 @@ export function MessageAudio(props: Props): JSX.Element {
)}
);
-
return (
{button}
- {waveform}
+
+
+ {fileName}
+
+ {waveform}
+
{metadata}
diff --git a/ts/state/selectors/audioPlayer.ts b/ts/state/selectors/audioPlayer.ts
index c4dfe2aa6c..2808750c15 100644
--- a/ts/state/selectors/audioPlayer.ts
+++ b/ts/state/selectors/audioPlayer.ts
@@ -34,6 +34,7 @@ export type VoiceNoteForPlayback = {
id: string;
// undefined if download is pending
url: string | undefined;
+ fileName: string | undefined;
type: 'incoming' | 'outgoing';
source: string | undefined;
sourceServiceId: ServiceIdString | undefined;
@@ -96,11 +97,13 @@ export function extractVoiceNoteForPlayback(
const voiceNoteUrl = attachment.path
? getAttachmentUrlForPath(attachment.path)
: undefined;
+ const fileName = attachment.fileName;
const status = getMessagePropStatus(message, ourConversationId);
return {
id: message.id,
url: voiceNoteUrl,
+ fileName,
type,
isPlayed: isPlayed(type, status, message.readStatus),
messageIdForLogging: getMessageIdForLogging(message),
diff --git a/ts/state/smart/MiniPlayer.tsx b/ts/state/smart/MiniPlayer.tsx
index 34a76bbb9d..7dd97f3aa3 100644
--- a/ts/state/smart/MiniPlayer.tsx
+++ b/ts/state/smart/MiniPlayer.tsx
@@ -41,6 +41,9 @@ export function SmartMiniPlayer({ shouldFlow }: Props): JSX.Element | null {
const url = AudioPlayerContent.isVoiceNote(content)
? content.current.url
: content.url;
+ const fileName = AudioPlayerContent.isVoiceNote(content)
+ ? content.current.fileName
+ : undefined
let state = PlayerState.loading;
if (url) {
@@ -55,6 +58,7 @@ export function SmartMiniPlayer({ shouldFlow }: Props): JSX.Element | null {
? i18n('icu:you')
: getVoiceNoteTitle(content.current)
}
+ fileName={fileName}
onPlay={handlePlay}
onPause={handlePause}
onPlaybackRate={setPlaybackRate}
diff --git a/ts/util/attachments.ts b/ts/util/attachments.ts
index 4e08af029b..e01a02112e 100644
--- a/ts/util/attachments.ts
+++ b/ts/util/attachments.ts
@@ -111,3 +111,35 @@ export function copyCdnFields(
plaintextHash: uploaded.plaintextHash,
};
}
+/**
+ * Shortens a file name based on specified conditions.
+ * @param fileName - The original file name.
+ * @param isPlaying - If true, truncate the file name to maxLength characters and add '...' at the end.
+ * - If false, show the first 15 characters, add '...', and the last 15 characters.
+ * @param maxLength - The maximum length of the file name (default: 30).
+ * @returns The shortened file name.
+ */
+export function shortenFileName(
+ fileName: string | undefined,
+ isPlaying: boolean = false,
+ maxLength: number = 30
+): string {
+ if (fileName === undefined) return '';
+ if (fileName.length <= maxLength) {
+ return fileName;
+ }
+
+ if (!isPlaying) {
+ const fileNameWithoutExtension = fileName.split('.').slice(0, -1).join('.');
+ const extension = fileName.split('.').pop();
+ const shortenedFileName = `${fileNameWithoutExtension.slice(
+ 0,
+ 15
+ )}...${fileNameWithoutExtension.slice(-15)}`;
+
+ return `${shortenedFileName}.${extension}`;
+ } else {
+ const truncatedFileName = `${fileName.slice(0, maxLength - 3)}...`;
+ return truncatedFileName;
+ }
+}