From 9e9c9bd6722eb2cf3f8596a1f8e7584dcbf19c6e Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 23 Feb 2024 14:05:38 +0100 Subject: [PATCH] One-time Voice: Add ability to create one-time voice (#4232) --- src/api/gramjs/apiBuilders/messages.ts | 2 + src/api/gramjs/methods/messages.ts | 3 +- src/api/types/misc.ts | 1 + src/assets/font-icons/one-filled.svg | 1 + src/assets/font-icons/view-once.svg | 7 +- src/components/common/Audio.scss | 43 ++-- src/components/common/Audio.tsx | 14 +- src/components/common/Composer.scss | 23 +- src/components/common/Composer.tsx | 58 ++++-- .../composer/hooks/useVoiceRecording.ts | 8 + src/config.ts | 2 + src/hooks/useAudioPlayer.ts | 10 +- src/styles/icons.scss | 196 +++++++++--------- src/styles/icons.woff | Bin 28476 -> 28388 bytes src/styles/icons.woff2 | Bin 23852 -> 23848 bytes src/types/icons/font.ts | 1 + 16 files changed, 217 insertions(+), 152 deletions(-) create mode 100644 src/assets/font-icons/one-filled.svg diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index bcd568728..fed83c3f6 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -929,6 +929,7 @@ function buildUploadingMedia( audio, shouldSendAsFile, shouldSendAsSpoiler, + ttlSeconds, } = attachment; if (!shouldSendAsFile) { @@ -973,6 +974,7 @@ function buildUploadingMedia( duration, waveform: inputWaveform, }, + ttlSeconds, }; } if (SUPPORTED_AUDIO_CONTENT_TYPES.has(mimeType)) { diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index cf8d40372..c5c04a936 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -624,7 +624,7 @@ export async function rescheduleMessage({ async function uploadMedia(localMessage: ApiMessage, attachment: ApiAttachment, onProgress: ApiOnProgress) { const { - filename, blobUrl, mimeType, quick, voice, audio, previewBlobUrl, shouldSendAsFile, shouldSendAsSpoiler, + filename, blobUrl, mimeType, quick, voice, audio, previewBlobUrl, shouldSendAsFile, shouldSendAsSpoiler, ttlSeconds, } = attachment; const patchedOnProgress: ApiOnProgress = (progress) => { @@ -698,6 +698,7 @@ async function uploadMedia(localMessage: ApiMessage, attachment: ApiAttachment, thumb, forceFile: shouldSendAsFile, spoiler: shouldSendAsSpoiler, + ttlSeconds, }); } diff --git a/src/api/types/misc.ts b/src/api/types/misc.ts index e204e4486..aa6f22940 100644 --- a/src/api/types/misc.ts +++ b/src/api/types/misc.ts @@ -52,6 +52,7 @@ export interface ApiAttachment { shouldSendAsSpoiler?: true; uniqueId?: string; + ttlSeconds?: number; } export interface ApiWallpaper { diff --git a/src/assets/font-icons/one-filled.svg b/src/assets/font-icons/one-filled.svg new file mode 100644 index 000000000..88076a85b --- /dev/null +++ b/src/assets/font-icons/one-filled.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/font-icons/view-once.svg b/src/assets/font-icons/view-once.svg index 7c58270b1..f4764edc5 100644 --- a/src/assets/font-icons/view-once.svg +++ b/src/assets/font-icons/view-once.svg @@ -1,6 +1 @@ - - - - - - + \ No newline at end of file diff --git a/src/components/common/Audio.scss b/src/components/common/Audio.scss index 155092941..54debfa94 100644 --- a/src/components/common/Audio.scss +++ b/src/components/common/Audio.scss @@ -26,6 +26,22 @@ .toogle-play-wrapper { margin: 0; + + .icon-view-once { + position: absolute; + padding: 0.125rem; + left: 2rem; + bottom: 0; + font-size: 1rem; + border-radius: 50%; + color: var(--color-white); + background-color: var(--color-primary); + outline: var(--background-color) solid 0.125rem; + z-index: var(--z-badge); + opacity: 1; + transform: scale(1); + transition: opacity 0.4s, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); + } .toggle-play { margin-inline-end: 0.5rem; @@ -66,27 +82,16 @@ transform: scale(1); transition: opacity 0.4s, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); } - - &.play .icon-pause, - &.pause .icon-play, - &.loading .icon-play, - &.loading .icon-pause, - &.loading .flame { - opacity: 0; - transform: scale(0.5); - } } - .icon-view-once { - position: absolute; - left: 2rem; - bottom: 0rem; - font-size: 1.1875rem; - border-radius: 50%; - color: var(--color-white); - background-color: var(--color-primary); - outline: var(--background-color) solid 0.125rem; - z-index: var(--z-badge); + &.play .icon-pause, + &.pause .icon-play, + &.loading .icon-play, + &.loading .icon-pause, + &.loading .flame, + &.loading .icon-view-once { + opacity: 0; + transform: scale(0.5); } } diff --git a/src/components/common/Audio.tsx b/src/components/common/Audio.tsx index 5cc544b20..7174524c4 100644 --- a/src/components/common/Audio.tsx +++ b/src/components/common/Audio.tsx @@ -123,7 +123,7 @@ const Audio: FC = ({ const { isRtl } = lang; const { isMobile } = useAppLayout(); - const [isActivated, setIsActivated] = useState(Boolean(autoPlay)); + const [isActivated, setIsActivated] = useState(false); const shouldLoad = isActivated || PRELOAD; const coverHash = getMessageMediaHash(message, 'pictogram'); const coverBlobUrl = useMedia(coverHash, false, ApiMediaFormat.BlobUrl); @@ -167,13 +167,14 @@ const Audio: FC = ({ bufferingHandlers, undefined, checkBuffering, - isActivated, + Boolean(isActivated || autoPlay), handleForcePlay, handleTrackChange, isMessageLocal(message) || hasTtl, undefined, onPause, noReset, + hasTtl && !isInOneTimeModal, ); const reversePlayProgress = 1 - playProgress; @@ -220,8 +221,7 @@ const Audio: FC = ({ } if (hasTtl) { - // Set new date to prevent saving state of the track - openOneTimeMediaModal({ message: { ...message, date: Date.now() } }); + openOneTimeMediaModal({ message }); onReadMedia?.(); return; } @@ -329,7 +329,7 @@ const Audio: FC = ({ isSelected && 'audio-is-selected', ); - const buttonClassNames = ['toggle-play']; + const buttonClassNames = ['toogle-play-wrapper']; if (shouldRenderCross) { buttonClassNames.push('loading'); } else { @@ -371,13 +371,13 @@ const Audio: FC = ({ function renderTooglePlayWrapper() { return ( -
+
+ {canSendOneTimeMedia && activeVoiceRecording && ( + + )} {activeVoiceRecording && (