One-time Voice: Add ability to create one-time voice (#4232)

This commit is contained in:
Alexander Zinchuk 2024-02-23 14:05:38 +01:00
parent e638a537dd
commit 9e9c9bd672
16 changed files with 217 additions and 152 deletions

View File

@ -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)) {

View File

@ -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,
});
}

View File

@ -52,6 +52,7 @@ export interface ApiAttachment {
shouldSendAsSpoiler?: true;
uniqueId?: string;
ttlSeconds?: number;
}
export interface ApiWallpaper {

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="M0 15C0 6.716 6.716 0 15 0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-8.284 0-15-6.716-15-15Zm13.636-6.818a1.364 1.364 0 1 0 0 2.727h.682c.377 0 .682.305.682.682v8.864a1.364 1.364 0 1 0 2.727 0V11.59a3.41 3.41 0 0 0-3.409-3.41z"/></svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@ -1,6 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
<g id="surface1">
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 16 29.328125 C 16.734375 29.328125 17.328125 28.734375 17.328125 28 C 17.328125 27.265625 16.734375 26.671875 16 26.671875 Z M 16 5.328125 C 16.734375 5.328125 17.328125 4.734375 17.328125 4 C 17.328125 3.265625 16.734375 2.671875 16 2.671875 Z M 16 26.671875 C 10.105469 26.671875 5.328125 21.894531 5.328125 16 L 2.671875 16 C 2.671875 23.359375 8.640625 29.328125 16 29.328125 Z M 5.328125 16 C 5.328125 10.105469 10.105469 5.328125 16 5.328125 L 16 2.671875 C 8.640625 2.671875 2.671875 8.640625 2.671875 16 Z M 5.328125 16 "/>
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 29.273438 14.777344 C 29.207031 14.046875 28.558594 13.507812 27.828125 13.574219 C 27.097656 13.640625 26.5625 14.289062 26.628906 15.019531 Z M 24.207031 9.179688 C 24.675781 9.742188 25.515625 9.820312 26.078125 9.351562 C 26.640625 8.882812 26.71875 8.042969 26.25 7.480469 Z M 24.519531 5.75 C 23.957031 5.28125 23.117188 5.359375 22.648438 5.921875 C 22.179688 6.484375 22.257812 7.324219 22.820312 7.792969 Z M 16.980469 5.371094 C 17.710938 5.4375 18.359375 4.902344 18.425781 4.171875 C 18.492188 3.441406 17.953125 2.792969 17.222656 2.726562 Z M 14.777344 2.726562 C 14.046875 2.792969 13.507812 3.441406 13.574219 4.171875 C 13.640625 4.902344 14.289062 5.4375 15.019531 5.371094 Z M 9.179688 7.792969 C 9.742188 7.324219 9.820312 6.484375 9.351562 5.921875 C 8.878906 5.359375 8.042969 5.28125 7.480469 5.75 Z M 5.75 7.480469 C 5.28125 8.042969 5.359375 8.882812 5.921875 9.351562 C 6.484375 9.820312 7.324219 9.742188 7.792969 9.179688 Z M 5.371094 15.019531 C 5.4375 14.289062 4.902344 13.640625 4.171875 13.574219 C 3.441406 13.507812 2.792969 14.046875 2.726562 14.777344 Z M 2.726562 17.222656 C 2.792969 17.953125 3.441406 18.492188 4.171875 18.425781 C 4.902344 18.359375 5.4375 17.710938 5.371094 16.980469 Z M 7.792969 22.820312 C 7.324219 22.257812 6.484375 22.179688 5.921875 22.648438 C 5.359375 23.121094 5.28125 23.957031 5.75 24.519531 Z M 7.480469 26.25 C 8.042969 26.71875 8.878906 26.640625 9.351562 26.078125 C 9.820312 25.515625 9.742188 24.675781 9.179688 24.207031 Z M 15.019531 26.628906 C 14.289062 26.5625 13.640625 27.097656 13.574219 27.828125 C 13.507812 28.558594 14.046875 29.207031 14.777344 29.273438 Z M 17.222656 29.273438 C 17.953125 29.207031 18.492188 28.558594 18.425781 27.828125 C 18.359375 27.097656 17.710938 26.5625 16.980469 26.628906 Z M 22.820312 24.207031 C 22.257812 24.675781 22.179688 25.515625 22.648438 26.078125 C 23.117188 26.640625 23.957031 26.71875 24.519531 26.25 Z M 26.25 24.519531 C 26.71875 23.957031 26.640625 23.121094 26.078125 22.648438 C 25.515625 22.179688 24.675781 22.257812 24.207031 22.820312 Z M 26.628906 16.980469 C 26.5625 17.710938 27.097656 18.359375 27.828125 18.425781 C 28.558594 18.492188 29.207031 17.953125 29.273438 17.222656 Z M 29.328125 16 C 29.328125 15.589844 29.308594 15.179688 29.273438 14.777344 L 26.628906 15.019531 C 26.65625 15.34375 26.671875 15.671875 26.671875 16 Z M 26.25 7.480469 C 25.726562 6.851562 25.148438 6.273438 24.519531 5.75 L 22.820312 7.792969 C 23.324219 8.210938 23.789062 8.675781 24.207031 9.179688 Z M 17.222656 2.726562 C 16.816406 2.691406 16.40625 2.671875 16 2.671875 L 16 5.328125 C 16.332031 5.328125 16.660156 5.34375 16.980469 5.371094 Z M 16 2.671875 C 15.589844 2.671875 15.179688 2.691406 14.777344 2.726562 L 15.019531 5.371094 C 15.34375 5.34375 15.671875 5.328125 16 5.328125 Z M 7.480469 5.75 C 6.851562 6.273438 6.273438 6.851562 5.75 7.480469 L 7.792969 9.179688 C 8.210938 8.675781 8.675781 8.210938 9.179688 7.792969 Z M 2.726562 14.777344 C 2.691406 15.183594 2.671875 15.59375 2.671875 16 L 5.328125 16 C 5.328125 15.667969 5.34375 15.339844 5.371094 15.019531 Z M 2.671875 16 C 2.671875 16.410156 2.691406 16.820312 2.726562 17.222656 L 5.371094 16.980469 C 5.34375 16.65625 5.328125 16.328125 5.328125 16 Z M 5.75 24.519531 C 6.273438 25.148438 6.851562 25.726562 7.480469 26.25 L 9.179688 24.207031 C 8.675781 23.789062 8.210938 23.324219 7.792969 22.820312 Z M 14.777344 29.273438 C 15.179688 29.308594 15.589844 29.328125 16 29.328125 L 16 26.671875 C 15.667969 26.671875 15.339844 26.65625 15.019531 26.628906 Z M 16 29.328125 C 16.410156 29.328125 16.820312 29.308594 17.222656 29.273438 L 16.980469 26.628906 C 16.65625 26.65625 16.328125 26.671875 16 26.671875 Z M 24.519531 26.25 C 25.148438 25.726562 25.726562 25.148438 26.25 24.519531 L 24.207031 22.820312 C 23.789062 23.324219 23.324219 23.789062 22.820312 24.207031 Z M 29.273438 17.222656 C 29.308594 16.820312 29.328125 16.410156 29.328125 16 L 26.671875 16 C 26.671875 16.332031 26.65625 16.660156 26.628906 16.980469 Z M 16.726562 22.996094 C 15.890625 22.996094 15.320312 22.433594 15.320312 21.582031 L 15.320312 11.898438 L 15.261719 11.898438 L 13.285156 13.273438 C 13.023438 13.460938 12.824219 13.527344 12.535156 13.527344 C 11.960938 13.527344 11.539062 13.117188 11.539062 12.515625 C 11.539062 12.085938 11.710938 11.765625 12.148438 11.457031 L 14.832031 9.601562 C 15.488281 9.148438 15.9375 9.066406 16.519531 9.066406 C 17.523438 9.066406 18.121094 9.675781 18.121094 10.648438 L 18.121094 21.582031 C 18.121094 22.433594 17.558594 22.996094 16.726562 22.996094 "/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path fill-rule="evenodd" d="M16 2.91C8.77 2.91 2.91 8.77 2.91 16c0 7.23 5.86 13.09 13.09 13.09.698 0 1.383-.054 2.05-.159a1.455 1.455 0 0 1 .452 2.874C17.686 31.934 16.85 32 16 32 7.163 32 0 24.837 0 16S7.163 0 16 0c.85 0 1.686.066 2.502.195a1.455 1.455 0 0 1-.452 2.874 13.2 13.2 0 0 0-2.05-.16Zm7.374.466a1.455 1.455 0 0 1 2.032-.32 16.084 16.084 0 0 1 3.539 3.538 1.455 1.455 0 1 1-2.353 1.712 13.175 13.175 0 0 0-2.898-2.898 1.455 1.455 0 0 1-.32-2.032Zm6.769 8.91a1.455 1.455 0 0 1 1.662 1.212 16.103 16.103 0 0 1 0 5.004 1.455 1.455 0 1 1-2.873-.452 13.206 13.206 0 0 0 0-4.1 1.455 1.455 0 0 1 1.21-1.663Zm-1.519 11.088c.65.473.793 1.383.32 2.032a16.083 16.083 0 0 1-3.538 3.539 1.455 1.455 0 1 1-1.712-2.353 13.174 13.174 0 0 0 2.898-2.898 1.455 1.455 0 0 1 2.032-.32ZM14.546 8.727a1.455 1.455 0 1 0 0 2.91h.727c.401 0 .727.325.727.726v9.455a1.454 1.454 0 1 0 2.91 0v-9.455a3.636 3.636 0 0 0-3.637-3.636h-.727Z" clip-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 1010 B

View File

@ -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);
}
}

View File

@ -123,7 +123,7 @@ const Audio: FC<OwnProps> = ({
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<OwnProps> = ({
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<OwnProps> = ({
}
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<OwnProps> = ({
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<OwnProps> = ({
function renderTooglePlayWrapper() {
return (
<div className="toogle-play-wrapper">
<div className={buildClassName(...buttonClassNames)}>
<Button
round
ripple={!isMobile}
size="smaller"
className="toggle-play"
color={coverBlobUrl ? 'translucent-white' : 'primary'}
className={buttonClassNames.join(' ')}
ariaLabel={isPlaying ? 'Pause audio' : 'Play audio'}
onClick={handleButtonClick}
isRtl={lang.isRtl}

View File

@ -63,7 +63,9 @@
.icon-schedule,
.icon-forward,
.icon-microphone-alt,
.icon-check {
.icon-check,
.icon-view-once,
.icon-one-filled {
position: absolute;
}
@ -123,7 +125,7 @@
}
}
&.send {
&.send, &.sendOneTime {
.icon-send {
animation: grow-icon 0.4s ease-out;
}
@ -192,6 +194,23 @@
}
}
&.view-once {
.icon-one-filled {
animation: hide-icon 0.4s forwards ease-out;
}
.icon-view-once {
animation: grow-icon 0.4s ease-out;
}
&.active {
.icon-view-once {
animation: hide-icon 0.4s forwards ease-out;
}
.icon-one-filled {
animation: grow-icon 0.4s ease-out;
}
}
}
&.not-ready > .icon {
animation-duration: 0ms !important;
}

View File

@ -40,6 +40,7 @@ import {
EDITABLE_INPUT_MODAL_ID,
HEART_REACTION,
MAX_UPLOAD_FILEPART_SIZE,
ONE_TIME_MEDIA_TTL_SECONDS,
REPLIES_USER_ID,
SCHEDULED_WHEN_ONLINE,
SEND_MESSAGE_ACTION_INTERVAL,
@ -157,6 +158,7 @@ import ResponsiveHoverButton from '../ui/ResponsiveHoverButton';
import Spinner from '../ui/Spinner';
import Avatar from './Avatar';
import DeleteMessageModal from './DeleteMessageModal.async';
import Icon from './Icon';
import ReactionAnimatedEmoji from './reactions/ReactionAnimatedEmoji';
import './Composer.scss';
@ -203,7 +205,7 @@ type StateProps =
botKeyboardMessageId?: number;
botKeyboardPlaceholder?: string;
withScheduledButton?: boolean;
shouldSchedule?: boolean;
isInScheduledList?: boolean;
canScheduleUntilOnline?: boolean;
stickersForEmoji?: ApiSticker[];
customEmojiForEmoji?: ApiSticker[];
@ -245,6 +247,7 @@ type StateProps =
shouldCollectDebugLogs?: boolean;
sentStoryReaction?: ApiReaction;
stealthMode?: ApiStealthMode;
canSendOneTimeMedia?: boolean;
};
enum MainButtonState {
@ -253,6 +256,7 @@ enum MainButtonState {
Edit = 'edit',
Schedule = 'schedule',
Forward = 'forward',
SendOneTime = 'sendOneTime',
}
type ScheduledMessageArgs = TabState['contentToBeScheduled'] | {
@ -273,7 +277,7 @@ const Composer: FC<OwnProps & StateProps> = ({
type,
isOnActiveTab,
dropAreaState,
shouldSchedule,
isInScheduledList,
canScheduleUntilOnline,
isReady,
isMobile,
@ -346,6 +350,7 @@ const Composer: FC<OwnProps & StateProps> = ({
shouldCollectDebugLogs,
sentStoryReaction,
stealthMode,
canSendOneTimeMedia,
onForward,
}) => {
const {
@ -544,6 +549,9 @@ const Composer: FC<OwnProps & StateProps> = ({
currentRecordTime,
recordButtonRef: mainButtonRef,
startRecordTimeRef,
isViewOnceEnabled,
setIsViewOnceEnabled,
toogleViewOnceEnabled,
} = useVoiceRecording();
const shouldSendRecordingStatus = isForCurrentMessageList && !isInStoryViewer;
@ -753,16 +761,16 @@ const Composer: FC<OwnProps & StateProps> = ({
return MainButtonState.Record;
}
if (shouldSchedule) {
if (isInScheduledList) {
return MainButtonState.Schedule;
}
return MainButtonState.Send;
}, [
activeVoiceRecording, editingMessage, getHtml, hasAttachments, isForwarding, isInputHasFocus, onForward,
shouldForceShowEditing, shouldSchedule,
shouldForceShowEditing, isInScheduledList,
]);
const canShowCustomSendMenu = !shouldSchedule;
const canShowCustomSendMenu = !isInScheduledList;
const {
isContextMenuOpen: isCustomSendMenuOpen,
@ -928,12 +936,13 @@ const Composer: FC<OwnProps & StateProps> = ({
if (activeVoiceRecording) {
const record = await stopRecordingVoice();
const ttlSeconds = isViewOnceEnabled ? ONE_TIME_MEDIA_TTL_SECONDS : undefined;
if (record) {
const { blob, duration, waveform } = record;
currentAttachments = [await buildAttachment(
VOICE_RECORDING_FILENAME,
blob,
{ voice: { duration, waveform } },
{ voice: { duration, waveform }, ttlSeconds },
)];
}
}
@ -1082,7 +1091,7 @@ const Composer: FC<OwnProps & StateProps> = ({
return;
}
if (shouldSchedule || isScheduleRequested) {
if (isInScheduledList || isScheduleRequested) {
forceShowSymbolMenu();
requestCalendar((scheduledAt) => {
cancelForceShowSymbolMenu();
@ -1115,7 +1124,7 @@ const Composer: FC<OwnProps & StateProps> = ({
isPreloadedGlobally: true,
};
if (shouldSchedule || isScheduleRequested) {
if (isInScheduledList || isScheduleRequested) {
forceShowSymbolMenu();
requestCalendar((scheduledAt) => {
cancelForceShowSymbolMenu();
@ -1144,7 +1153,7 @@ const Composer: FC<OwnProps & StateProps> = ({
return;
}
if (shouldSchedule || isScheduleRequested) {
if (isInScheduledList || isScheduleRequested) {
requestCalendar((scheduledAt) => {
handleMessageSchedule({
id: inlineResult.id,
@ -1184,7 +1193,7 @@ const Composer: FC<OwnProps & StateProps> = ({
return;
}
if (shouldSchedule) {
if (isInScheduledList) {
requestCalendar((scheduledAt) => {
handleMessageSchedule({ poll }, scheduledAt, currentMessageList);
});
@ -1196,7 +1205,7 @@ const Composer: FC<OwnProps & StateProps> = ({
});
const sendSilent = useLastCallback((additionalArgs?: ScheduledMessageArgs) => {
if (shouldSchedule) {
if (isInScheduledList) {
requestCalendar((scheduledAt) => {
handleMessageSchedule({ ...additionalArgs, isSilent: true }, scheduledAt, currentMessageList!);
});
@ -1340,6 +1349,7 @@ const Composer: FC<OwnProps & StateProps> = ({
showAllowedMessageTypesNotification({ chatId });
}
} else {
setIsViewOnceEnabled(false);
void startRecordingVoice();
}
break;
@ -1513,7 +1523,7 @@ const Composer: FC<OwnProps & StateProps> = ({
shouldForceAsFile={shouldForceAsFile}
isForCurrentMessageList={isForCurrentMessageList}
isForMessage={isInMessageList}
shouldSchedule={shouldSchedule}
shouldSchedule={isInScheduledList}
forceDarkTheme={isInStoryViewer}
onCaptionUpdate={onCaptionUpdate}
onSendSilent={handleSendSilentAttachments}
@ -1762,7 +1772,7 @@ const Composer: FC<OwnProps & StateProps> = ({
canSendAudios={canSendAudios}
onFileSelect={handleFileSelect}
onPollCreate={openPollModal}
isScheduled={shouldSchedule}
isScheduled={isInScheduledList}
attachBots={isInMessageList ? attachBots : undefined}
peerType={attachMenuPeerType}
shouldCollectDebugLogs={shouldCollectDebugLogs}
@ -1813,6 +1823,18 @@ const Composer: FC<OwnProps & StateProps> = ({
/>
</div>
</div>
{canSendOneTimeMedia && activeVoiceRecording && (
<Button
className={buildClassName('view-once', isViewOnceEnabled && 'active')}
round
color="secondary"
ariaLabel={lang('Chat.PlayOnceVoiceMessageTooltip')}
onClick={toogleViewOnceEnabled}
>
<Icon name="view-once" />
<Icon name="one-filled" />
</Button>
)}
{activeVoiceRecording && (
<Button
round
@ -1883,10 +1905,10 @@ const Composer: FC<OwnProps & StateProps> = ({
{canShowCustomSendMenu && (
<CustomSendMenu
isOpen={isCustomSendMenuOpen}
canSchedule={isInMessageList}
canScheduleUntilOnline={canScheduleUntilOnline}
canSchedule={isInMessageList && !isViewOnceEnabled}
canScheduleUntilOnline={canScheduleUntilOnline && !isViewOnceEnabled}
onSendSilent={!isChatWithSelf ? handleSendSilent : undefined}
onSendSchedule={!shouldSchedule ? handleSendScheduled : undefined}
onSendSchedule={!isInScheduledList ? handleSendScheduled : undefined}
onSendWhenOnline={handleSendWhenOnline}
onClose={handleContextMenuClose}
onCloseAnimationEnd={handleContextMenuHide}
@ -1958,6 +1980,7 @@ export default memo(withGlobal<OwnProps>(
const replyToTopic = chat?.isForum && chat.isForumAsMessages && threadId === MAIN_THREAD_ID && replyToMessage
? selectTopicFromMessage(global, replyToMessage)
: undefined;
const isInScheduledList = messageListType === 'scheduled';
return {
availableReactions: type === 'story' ? global.availableReactions : undefined,
@ -1977,7 +2000,7 @@ export default memo(withGlobal<OwnProps>(
messageListType === 'thread'
&& Boolean(scheduledIds?.length)
),
shouldSchedule: messageListType === 'scheduled',
isInScheduledList,
botKeyboardMessageId,
botKeyboardPlaceholder: keyboardMessage?.keyboardPlaceholder,
isForwarding: chatId === tabState.forwardMessages.toChatId,
@ -2019,6 +2042,7 @@ export default memo(withGlobal<OwnProps>(
isReactionPickerOpen: selectIsReactionPickerOpen(global),
canBuyPremium: !isCurrentUserPremium && !selectIsPremiumPurchaseBlocked(global),
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
canSendOneTimeMedia: isChatWithUser && !isChatWithBot && !isInScheduledList,
shouldCollectDebugLogs: global.settings.byKey.shouldCollectDebugLogs,
sentStoryReaction,
stealthMode: global.stories.stealthMode,

View File

@ -17,6 +17,7 @@ const useVoiceRecording = () => {
const [activeVoiceRecording, setActiveVoiceRecording] = useState<ActiveVoiceRecording>();
const startRecordTimeRef = useRef<number>();
const [currentRecordTime, setCurrentRecordTime] = useState<number | undefined>();
const [isViewOnceEnabled, setIsViewOnceEnabled] = useState(false);
useEffect(() => {
// Preloading worker fixes silent first record on iOS
@ -96,6 +97,10 @@ const useVoiceRecording = () => {
return activeVoiceRecording ? captureEscKeyListener(stopRecordingVoice) : undefined;
}, [activeVoiceRecording, stopRecordingVoice]);
const toogleViewOnceEnabled = useLastCallback(() => {
setIsViewOnceEnabled(!isViewOnceEnabled);
});
return {
startRecordingVoice,
pauseRecordingVoice,
@ -104,6 +109,9 @@ const useVoiceRecording = () => {
currentRecordTime,
recordButtonRef,
startRecordTimeRef,
isViewOnceEnabled,
setIsViewOnceEnabled,
toogleViewOnceEnabled,
};
};

View File

@ -343,3 +343,5 @@ export const DEFAULT_LIMITS: Record<ApiLimitType, readonly [number, number]> = {
recommendedChannels: [10, 100],
savedDialogsPinned: [5, 100],
};
export const ONE_TIME_MEDIA_TTL_SECONDS = 2147483647;

View File

@ -34,6 +34,7 @@ const useAudioPlayer = (
noProgressUpdates = false,
onPause?: NoneToVoidFunction,
noReset = false,
noHandleEvents = false,
) => {
// eslint-disable-next-line no-null/no-null
const controllerRef = useRef<ReturnType<typeof register>>(null);
@ -50,6 +51,9 @@ const useAudioPlayer = (
useSyncEffect(() => {
controllerRef.current = register(trackId, trackType, (eventName, e) => {
if (noHandleEvents) {
return;
}
switch (eventName) {
case 'onPlay': {
const {
@ -67,7 +71,6 @@ const useAudioPlayer = (
if (trackType === 'voice' || duration > PLAYBACK_RATE_FOR_AUDIO_MIN_DURATION) {
setPlaybackRate(audioPlayer.playbackRate);
}
setPositionState({
duration: proxy.duration || 0,
playbackRate: proxy.playbackRate,
@ -103,7 +106,6 @@ const useAudioPlayer = (
break;
}
}
handlers?.[eventName]?.(e);
}, onForcePlay, handleTrackChange);
@ -116,7 +118,7 @@ const useAudioPlayer = (
isPlayingSync = true;
}
if (onInit) {
if (onInit && !noHandleEvents) {
onInit(proxy);
}
}, [trackId]);
@ -159,7 +161,7 @@ const useAudioPlayer = (
// Autoplay once `src` is present
useEffectWithPrevDeps(([prevShouldPlay, prevSrc]) => {
if (prevShouldPlay === shouldPlay && src === prevSrc && trackType !== 'oneTimeVoice') {
if (prevShouldPlay === shouldPlay && src === prevSrc) {
return;
}

View File

@ -157,102 +157,103 @@ $icons-map: (
"next": "\f17e",
"noise-suppression": "\f17f",
"non-contacts": "\f180",
"open-in-new-tab": "\f181",
"password-off": "\f182",
"pause": "\f183",
"permissions": "\f184",
"phone-discard-outline": "\f185",
"phone-discard": "\f186",
"phone": "\f187",
"photo": "\f188",
"pin-badge": "\f189",
"pin-list": "\f18a",
"pin": "\f18b",
"pinned-chat": "\f18c",
"pinned-message": "\f18d",
"pip": "\f18e",
"play-story": "\f18f",
"play": "\f190",
"poll": "\f191",
"premium": "\f192",
"previous": "\f193",
"privacy-policy": "\f194",
"quote-text": "\f195",
"quote": "\f196",
"readchats": "\f197",
"recent": "\f198",
"reload": "\f199",
"remove": "\f19a",
"reopen-topic": "\f19b",
"replace": "\f19c",
"replies": "\f19d",
"reply-filled": "\f19e",
"reply": "\f19f",
"revote": "\f1a0",
"save-story": "\f1a1",
"saved-messages": "\f1a2",
"schedule": "\f1a3",
"search": "\f1a4",
"select": "\f1a5",
"send-outline": "\f1a6",
"send": "\f1a7",
"settings-filled": "\f1a8",
"settings": "\f1a9",
"share-filled": "\f1aa",
"share-screen-outlined": "\f1ab",
"share-screen-stop": "\f1ac",
"share-screen": "\f1ad",
"sidebar": "\f1ae",
"skip-next": "\f1af",
"skip-previous": "\f1b0",
"smallscreen": "\f1b1",
"smile": "\f1b2",
"sort": "\f1b3",
"speaker-muted-story": "\f1b4",
"speaker-outline": "\f1b5",
"speaker-story": "\f1b6",
"speaker": "\f1b7",
"spoiler-disable": "\f1b8",
"spoiler": "\f1b9",
"sport": "\f1ba",
"stats": "\f1bb",
"stealth-future": "\f1bc",
"stealth-past": "\f1bd",
"stickers": "\f1be",
"stop-raising-hand": "\f1bf",
"stop": "\f1c0",
"story-caption": "\f1c1",
"story-expired": "\f1c2",
"story-priority": "\f1c3",
"story-reply": "\f1c4",
"strikethrough": "\f1c5",
"timer": "\f1c6",
"transcribe": "\f1c7",
"truck": "\f1c8",
"unarchive": "\f1c9",
"underlined": "\f1ca",
"unlock-badge": "\f1cb",
"unlock": "\f1cc",
"unmute": "\f1cd",
"unpin": "\f1ce",
"unread": "\f1cf",
"up": "\f1d0",
"user-filled": "\f1d1",
"user-online": "\f1d2",
"user": "\f1d3",
"video-outlined": "\f1d4",
"video-stop": "\f1d5",
"video": "\f1d6",
"view-once": "\f1d7",
"voice-chat": "\f1d8",
"volume-1": "\f1d9",
"volume-2": "\f1da",
"volume-3": "\f1db",
"web": "\f1dc",
"webapp": "\f1dd",
"word-wrap": "\f1de",
"zoom-in": "\f1df",
"zoom-out": "\f1e0",
"one-filled": "\f181",
"open-in-new-tab": "\f182",
"password-off": "\f183",
"pause": "\f184",
"permissions": "\f185",
"phone-discard-outline": "\f186",
"phone-discard": "\f187",
"phone": "\f188",
"photo": "\f189",
"pin-badge": "\f18a",
"pin-list": "\f18b",
"pin": "\f18c",
"pinned-chat": "\f18d",
"pinned-message": "\f18e",
"pip": "\f18f",
"play-story": "\f190",
"play": "\f191",
"poll": "\f192",
"premium": "\f193",
"previous": "\f194",
"privacy-policy": "\f195",
"quote-text": "\f196",
"quote": "\f197",
"readchats": "\f198",
"recent": "\f199",
"reload": "\f19a",
"remove": "\f19b",
"reopen-topic": "\f19c",
"replace": "\f19d",
"replies": "\f19e",
"reply-filled": "\f19f",
"reply": "\f1a0",
"revote": "\f1a1",
"save-story": "\f1a2",
"saved-messages": "\f1a3",
"schedule": "\f1a4",
"search": "\f1a5",
"select": "\f1a6",
"send-outline": "\f1a7",
"send": "\f1a8",
"settings-filled": "\f1a9",
"settings": "\f1aa",
"share-filled": "\f1ab",
"share-screen-outlined": "\f1ac",
"share-screen-stop": "\f1ad",
"share-screen": "\f1ae",
"sidebar": "\f1af",
"skip-next": "\f1b0",
"skip-previous": "\f1b1",
"smallscreen": "\f1b2",
"smile": "\f1b3",
"sort": "\f1b4",
"speaker-muted-story": "\f1b5",
"speaker-outline": "\f1b6",
"speaker-story": "\f1b7",
"speaker": "\f1b8",
"spoiler-disable": "\f1b9",
"spoiler": "\f1ba",
"sport": "\f1bb",
"stats": "\f1bc",
"stealth-future": "\f1bd",
"stealth-past": "\f1be",
"stickers": "\f1bf",
"stop-raising-hand": "\f1c0",
"stop": "\f1c1",
"story-caption": "\f1c2",
"story-expired": "\f1c3",
"story-priority": "\f1c4",
"story-reply": "\f1c5",
"strikethrough": "\f1c6",
"timer": "\f1c7",
"transcribe": "\f1c8",
"truck": "\f1c9",
"unarchive": "\f1ca",
"underlined": "\f1cb",
"unlock-badge": "\f1cc",
"unlock": "\f1cd",
"unmute": "\f1ce",
"unpin": "\f1cf",
"unread": "\f1d0",
"up": "\f1d1",
"user-filled": "\f1d2",
"user-online": "\f1d3",
"user": "\f1d4",
"video-outlined": "\f1d5",
"video-stop": "\f1d6",
"video": "\f1d7",
"view-once": "\f1d8",
"voice-chat": "\f1d9",
"volume-1": "\f1da",
"volume-2": "\f1db",
"volume-3": "\f1dc",
"web": "\f1dd",
"webapp": "\f1de",
"word-wrap": "\f1df",
"zoom-in": "\f1e0",
"zoom-out": "\f1e1",
);
.icon-active-sessions::before {
@ -639,6 +640,9 @@ $icons-map: (
.icon-non-contacts::before {
content: map.get($icons-map, "non-contacts");
}
.icon-one-filled::before {
content: map.get($icons-map, "one-filled");
}
.icon-open-in-new-tab::before {
content: map.get($icons-map, "open-in-new-tab");
}

Binary file not shown.

Binary file not shown.

View File

@ -127,6 +127,7 @@ export type FontIconName =
| 'next'
| 'noise-suppression'
| 'non-contacts'
| 'one-filled'
| 'open-in-new-tab'
| 'password-off'
| 'pause'