Various fixes (#1461)
* Show round videos in the voices tab * Pause audio player when starting round video playback * Changed text for empty votes tab (taken from TDesktop) * Capitalized month name on Shared Media tabs. * Display title context menu button in unjoined channels or groups * Fixed voice recording timer flickering * Don't restart emoji animation when pressed while animation is playing * Corrected viewport calculation for iOS15 * Changed the border color of avatars in own poll
This commit is contained in:
parent
59be7ae021
commit
c34d389252
@ -813,7 +813,7 @@ export async function searchMessagesLocal({
|
|||||||
filter = new GramJs.InputMessagesFilterMusic();
|
filter = new GramJs.InputMessagesFilterMusic();
|
||||||
break;
|
break;
|
||||||
case 'voice':
|
case 'voice':
|
||||||
filter = new GramJs.InputMessagesFilterVoice();
|
filter = new GramJs.InputMessagesFilterRoundVoice();
|
||||||
break;
|
break;
|
||||||
case 'profilePhoto':
|
case 'profilePhoto':
|
||||||
filter = new GramJs.InputMessagesFilterChatPhotos();
|
filter = new GramJs.InputMessagesFilterChatPhotos();
|
||||||
@ -890,7 +890,7 @@ export async function searchMessagesGlobal({
|
|||||||
filter = new GramJs.InputMessagesFilterMusic();
|
filter = new GramJs.InputMessagesFilterMusic();
|
||||||
break;
|
break;
|
||||||
case 'voice':
|
case 'voice':
|
||||||
filter = new GramJs.InputMessagesFilterVoice();
|
filter = new GramJs.InputMessagesFilterRoundVoice();
|
||||||
break;
|
break;
|
||||||
case 'text':
|
case 'text':
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@ -170,7 +170,7 @@ const AnimatedSticker: FC<OwnProps> = ({
|
|||||||
if (play || playSegment) {
|
if (play || playSegment) {
|
||||||
if (isFrozen.current) {
|
if (isFrozen.current) {
|
||||||
wasPlaying.current = true;
|
wasPlaying.current = true;
|
||||||
} else {
|
} else if (!animation.isPlaying()) {
|
||||||
playAnimation(noLoop);
|
playAnimation(noLoop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -79,8 +79,8 @@ const Audio: FC<OwnProps> = ({
|
|||||||
onCancelUpload,
|
onCancelUpload,
|
||||||
onDateClick,
|
onDateClick,
|
||||||
}) => {
|
}) => {
|
||||||
const { content: { audio, voice }, isMediaUnread } = message;
|
const { content: { audio, voice, video }, isMediaUnread } = message;
|
||||||
const isVoice = Boolean(voice);
|
const isVoice = Boolean(voice || video);
|
||||||
const isSeeking = useRef<boolean>(false);
|
const isSeeking = useRef<boolean>(false);
|
||||||
const playStateBeforeSeeking = useRef<boolean>(false);
|
const playStateBeforeSeeking = useRef<boolean>(false);
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -229,7 +229,7 @@ const Audio: FC<OwnProps> = ({
|
|||||||
if (isVoice) {
|
if (isVoice) {
|
||||||
return (
|
return (
|
||||||
<div className="meta" dir={isRtl ? 'rtl' : undefined}>
|
<div className="meta" dir={isRtl ? 'rtl' : undefined}>
|
||||||
{formatMediaDuration(voice!.duration)}
|
{formatMediaDuration((voice || video)!.duration)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -359,7 +359,7 @@ const Audio: FC<OwnProps> = ({
|
|||||||
lang, audio, duration, isPlaying, playProgress, bufferedProgress, seekerRef, (isDownloadStarted || isUploading),
|
lang, audio, duration, isPlaying, playProgress, bufferedProgress, seekerRef, (isDownloadStarted || isUploading),
|
||||||
date, transferProgress, onDateClick ? handleDateClick : undefined,
|
date, transferProgress, onDateClick ? handleDateClick : undefined,
|
||||||
)}
|
)}
|
||||||
{origin === AudioOrigin.SharedMedia && voice && renderWithTitle()}
|
{origin === AudioOrigin.SharedMedia && (voice || video) && renderWithTitle()}
|
||||||
{origin === AudioOrigin.Inline && voice && renderVoice(voice, renderedWaveform, playProgress, isMediaUnread)}
|
{origin === AudioOrigin.Inline && voice && renderVoice(voice, renderedWaveform, playProgress, isMediaUnread)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -408,7 +408,7 @@ function renderAudio(
|
|||||||
{date && (
|
{date && (
|
||||||
<>
|
<>
|
||||||
<span className="bullet">•</span>
|
<span className="bullet">•</span>
|
||||||
<Link className="date" onClick={handleDateClick}>{formatMediaDateTime(lang, date * 1000)}</Link>
|
<Link className="date" onClick={handleDateClick}>{formatMediaDateTime(lang, date * 1000, true)}</Link>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -147,8 +147,8 @@ const File: FC<OwnProps> = ({
|
|||||||
{sender && <span className="file-sender">{renderText(sender)}</span>}
|
{sender && <span className="file-sender">{renderText(sender)}</span>}
|
||||||
{!sender && timestamp && (
|
{!sender && timestamp && (
|
||||||
<>
|
<>
|
||||||
{' '}
|
<span className="bullet" />
|
||||||
<Link onClick={onDateClick}>{formatMediaDateTime(lang, timestamp * 1000)}</Link>
|
<Link onClick={onDateClick}>{formatMediaDateTime(lang, timestamp * 1000, true)}</Link>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -62,7 +62,7 @@ const SenderInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
{senderTitle && renderText(senderTitle)}
|
{senderTitle && renderText(senderTitle)}
|
||||||
</div>
|
</div>
|
||||||
<div className="date" dir="auto">
|
<div className="date" dir="auto">
|
||||||
{isAvatar ? lang('lng_mediaview_profile_photo') : formatMediaDateTime(lang, message!.date * 1000)}
|
{isAvatar ? lang('lng_mediaview_profile_photo') : formatMediaDateTime(lang, message!.date * 1000, true)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -162,21 +162,19 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<i className="icon-search" />
|
<i className="icon-search" />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{(IS_SINGLE_COLUMN_LAYOUT || !canSubscribe) && (
|
<Button
|
||||||
<Button
|
ref={menuButtonRef}
|
||||||
ref={menuButtonRef}
|
className={isMenuOpen ? 'active' : ''}
|
||||||
className={isMenuOpen ? 'active' : ''}
|
round
|
||||||
round
|
ripple={!IS_SINGLE_COLUMN_LAYOUT}
|
||||||
ripple={!IS_SINGLE_COLUMN_LAYOUT}
|
size="smaller"
|
||||||
size="smaller"
|
color="translucent"
|
||||||
color="translucent"
|
disabled={noMenu}
|
||||||
disabled={noMenu}
|
ariaLabel="More actions"
|
||||||
ariaLabel="More actions"
|
onClick={handleHeaderMenuOpen}
|
||||||
onClick={handleHeaderMenuOpen}
|
>
|
||||||
>
|
<i className="icon-more" />
|
||||||
<i className="icon-more" />
|
</Button>
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{menuPosition && (
|
{menuPosition && (
|
||||||
<HeaderMenuContainer
|
<HeaderMenuContainer
|
||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
@ -226,15 +224,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const canMute = isMainThread && !isChatWithSelf && !canSubscribe;
|
const canMute = isMainThread && !isChatWithSelf && !canSubscribe;
|
||||||
const canLeave = isMainThread && !canSubscribe;
|
const canLeave = isMainThread && !canSubscribe;
|
||||||
|
|
||||||
const noMenu = !(
|
|
||||||
(IS_SINGLE_COLUMN_LAYOUT && canSubscribe)
|
|
||||||
|| (IS_SINGLE_COLUMN_LAYOUT && canSearch)
|
|
||||||
|| canMute
|
|
||||||
|| canLeave
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
noMenu,
|
noMenu: false,
|
||||||
isChannel,
|
isChannel,
|
||||||
isRightColumnShown,
|
isRightColumnShown,
|
||||||
canStartBot,
|
canStartBot,
|
||||||
|
|||||||
@ -267,17 +267,19 @@
|
|||||||
line-height: 3.5rem;
|
line-height: 3.5rem;
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
padding: 0 3.125rem 0 1rem;
|
padding: 0 3.125rem 0 1rem;
|
||||||
|
font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Helvetica Neue", sans-serif;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
width: 10px;
|
width: .75rem;
|
||||||
height: 10px;
|
height: .75rem;
|
||||||
background: var(--color-error);
|
background: var(--color-error);
|
||||||
border-radius: 5px;
|
border-radius: .375rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
margin-top: -5px;
|
margin-top: -.375rem;
|
||||||
right: 1.375rem;
|
right: 1.3125rem;
|
||||||
|
animation: recording-blink-like-macos 1.5s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
@ -478,3 +480,12 @@
|
|||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes recording-blink-like-macos {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: .3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -121,10 +121,14 @@
|
|||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
|
|
||||||
.Avatar {
|
.Avatar {
|
||||||
border: 1px solid var(--color-white);
|
border: .0625rem solid var(--color-white);
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
.Message.own & {
|
||||||
|
border: .0625rem solid var(--secondary-color);
|
||||||
|
}
|
||||||
|
|
||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
margin-left: -3px;
|
margin-left: -3px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import useTransitionForMedia from '../../../hooks/useTransitionForMedia';
|
|||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
import useBuffering from '../../../hooks/useBuffering';
|
import useBuffering from '../../../hooks/useBuffering';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
import { stopCurrentAudio } from '../../../util/audioPlayer';
|
||||||
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
import useHeavyAnimationCheckForVideo from '../../../hooks/useHeavyAnimationCheckForVideo';
|
||||||
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
import useVideoCleanup from '../../../hooks/useVideoCleanup';
|
||||||
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
import usePauseOnInactive from './hooks/usePauseOnInactive';
|
||||||
@ -156,6 +157,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
if (isActivated) {
|
if (isActivated) {
|
||||||
if (playerEl.paused) {
|
if (playerEl.paused) {
|
||||||
safePlay(playerEl);
|
safePlay(playerEl);
|
||||||
|
stopCurrentAudio();
|
||||||
} else {
|
} else {
|
||||||
playerEl.pause();
|
playerEl.pause();
|
||||||
}
|
}
|
||||||
@ -165,6 +167,7 @@ const RoundVideo: FC<OwnProps> = ({
|
|||||||
playerEl.pause();
|
playerEl.pause();
|
||||||
playerEl.currentTime = 0;
|
playerEl.currentTime = 0;
|
||||||
safePlay(playerEl);
|
safePlay(playerEl);
|
||||||
|
stopCurrentAudio();
|
||||||
|
|
||||||
setIsActivated(true);
|
setIsActivated(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -271,14 +271,16 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
text = areMembersHidden ? 'You have no access to group members list.' : 'No members found';
|
||||||
break;
|
break;
|
||||||
case 'documents':
|
case 'documents':
|
||||||
text = lang('lng_media_file_empty_search');
|
text = lang('lng_media_file_empty');
|
||||||
break;
|
break;
|
||||||
case 'links':
|
case 'links':
|
||||||
text = lang('lng_media_link_empty_search');
|
text = lang('lng_media_link_empty');
|
||||||
|
break;
|
||||||
|
case 'audio':
|
||||||
|
text = lang('lng_media_song_empty');
|
||||||
break;
|
break;
|
||||||
case 'voice':
|
case 'voice':
|
||||||
case 'audio':
|
text = lang('lng_media_audio_empty');
|
||||||
text = lang('lng_media_song_empty_search');
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
text = lang('SharedMedia.EmptyTitle');
|
text = lang('SharedMedia.EmptyTitle');
|
||||||
|
|||||||
@ -366,7 +366,10 @@ export function getMessageContentIds(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'voice':
|
case 'voice':
|
||||||
validator = getMessageVoice;
|
validator = (message: ApiMessage) => {
|
||||||
|
const video = getMessageVideo(message);
|
||||||
|
return getMessageVoice(message) || (video && video.isRound);
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'inlineMedia':
|
case 'inlineMedia':
|
||||||
|
|||||||
@ -75,20 +75,26 @@ export function formatMonthAndYear(lang: LangFn, date: Date, isShort = false) {
|
|||||||
return formatDate(lang, date, format);
|
return formatDate(lang, date, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatHumanDate(lang: LangFn, datetime: number | Date, isShort = false, noWeekdays = false) {
|
export function formatHumanDate(
|
||||||
|
lang: LangFn,
|
||||||
|
datetime: number | Date,
|
||||||
|
isShort = false,
|
||||||
|
noWeekdays = false,
|
||||||
|
isUpperFirst?: boolean,
|
||||||
|
) {
|
||||||
const date = typeof datetime === 'number' ? new Date(datetime) : datetime;
|
const date = typeof datetime === 'number' ? new Date(datetime) : datetime;
|
||||||
|
|
||||||
const today = getDayStart(new Date());
|
const today = getDayStart(new Date());
|
||||||
|
|
||||||
if (!noWeekdays) {
|
if (!noWeekdays) {
|
||||||
if (toIsoString(date) === toIsoString(today)) {
|
if (toIsoString(date) === toIsoString(today)) {
|
||||||
return (isShort ? lowerFirst : upperFirst)(lang('Weekday.Today'));
|
return (isUpperFirst || !isShort ? upperFirst : lowerFirst)(lang('Weekday.Today'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const yesterday = new Date(today);
|
const yesterday = new Date(today);
|
||||||
yesterday.setDate(today.getDate() - 1);
|
yesterday.setDate(today.getDate() - 1);
|
||||||
if (toIsoString(date) === toIsoString(yesterday)) {
|
if (toIsoString(date) === toIsoString(yesterday)) {
|
||||||
return (isShort ? lowerFirst : upperFirst)(lang('Weekday.Yesterday'));
|
return (isUpperFirst || !isShort ? upperFirst : lowerFirst)(lang('Weekday.Yesterday'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const weekAgo = new Date(today);
|
const weekAgo = new Date(today);
|
||||||
@ -97,9 +103,9 @@ export function formatHumanDate(lang: LangFn, datetime: number | Date, isShort =
|
|||||||
weekAhead.setDate(today.getDate() + 7);
|
weekAhead.setDate(today.getDate() + 7);
|
||||||
if (date >= weekAgo && date <= weekAhead) {
|
if (date >= weekAgo && date <= weekAhead) {
|
||||||
const weekDay = WEEKDAYS_FULL[date.getDay()];
|
const weekDay = WEEKDAYS_FULL[date.getDay()];
|
||||||
return isShort
|
const weekDayString = isShort ? lang(`Weekday.Short${weekDay}`) : lang(`Weekday.${weekDay}`);
|
||||||
? lowerFirst(lang(`Weekday.Short${weekDay}`))
|
|
||||||
: upperFirst(lang(`Weekday.${weekDay}`));
|
return (isUpperFirst || !isShort ? upperFirst : lowerFirst)(weekDayString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +115,7 @@ export function formatHumanDate(lang: LangFn, datetime: number | Date, isShort =
|
|||||||
: (withYear ? 'chatFullDate' : 'chatDate');
|
: (withYear ? 'chatFullDate' : 'chatDate');
|
||||||
const format = lang(formatKey) || 'd MMMM yyyy';
|
const format = lang(formatKey) || 'd MMMM yyyy';
|
||||||
|
|
||||||
return (isShort ? lowerFirst : upperFirst)(formatDate(lang, date, format));
|
return (isUpperFirst || !isShort ? upperFirst : lowerFirst)(formatDate(lang, date, format));
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(lang: LangFn, date: Date, format: string) {
|
function formatDate(lang: LangFn, date: Date, format: string) {
|
||||||
@ -126,10 +132,10 @@ function formatDate(lang: LangFn, date: Date, format: string) {
|
|||||||
.replace('yyyy', String(date.getFullYear()));
|
.replace('yyyy', String(date.getFullYear()));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatMediaDateTime(lang: LangFn, datetime: number | Date) {
|
export function formatMediaDateTime(lang: LangFn, datetime: number | Date, isUpperFirst?: boolean) {
|
||||||
const date = typeof datetime === 'number' ? new Date(datetime) : datetime;
|
const date = typeof datetime === 'number' ? new Date(datetime) : datetime;
|
||||||
|
|
||||||
return `${formatHumanDate(lang, date, true)}, ${formatTime(date)}`;
|
return `${formatHumanDate(lang, date, true, undefined, isUpperFirst)}, ${formatTime(date)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatMediaDuration(duration: number, maxValue?: number) {
|
export function formatMediaDuration(duration: number, maxValue?: number) {
|
||||||
|
|||||||
@ -36,11 +36,21 @@ const handleResize = throttle(() => {
|
|||||||
}
|
}
|
||||||
}, 250, true);
|
}, 250, true);
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
window.addEventListener('orientationchange', handleResize);
|
window.addEventListener('orientationchange', handleResize);
|
||||||
|
if (IS_IOS) {
|
||||||
|
window.visualViewport.addEventListener('resize', handleResize);
|
||||||
|
} else {
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
}
|
||||||
|
|
||||||
export function updateSizes(): IDimensions {
|
export function updateSizes(): IDimensions {
|
||||||
const vh = window.innerHeight * 0.01;
|
let height: number;
|
||||||
|
if (IS_IOS) {
|
||||||
|
height = window.visualViewport.height + window.visualViewport.pageTop;
|
||||||
|
} else {
|
||||||
|
height = window.innerHeight;
|
||||||
|
}
|
||||||
|
const vh = height * 0.01;
|
||||||
|
|
||||||
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user