One-time Voice: Add ability to create one-time voice (#4232)
This commit is contained in:
parent
e638a537dd
commit
9e9c9bd672
@ -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)) {
|
||||
|
||||
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ export interface ApiAttachment {
|
||||
shouldSendAsSpoiler?: true;
|
||||
|
||||
uniqueId?: string;
|
||||
ttlSeconds?: number;
|
||||
}
|
||||
|
||||
export interface ApiWallpaper {
|
||||
|
||||
1
src/assets/font-icons/one-filled.svg
Normal file
1
src/assets/font-icons/one-filled.svg
Normal 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 |
@ -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 |
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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.
@ -127,6 +127,7 @@ export type FontIconName =
|
||||
| 'next'
|
||||
| 'noise-suppression'
|
||||
| 'non-contacts'
|
||||
| 'one-filled'
|
||||
| 'open-in-new-tab'
|
||||
| 'password-off'
|
||||
| 'pause'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user