Media Viewer: Allow to hide caption by tap on mobile (#1196)

This commit is contained in:
Alexander Zinchuk 2021-06-22 13:54:25 +03:00
parent c6550ca3e4
commit 2c7c23715c
49 changed files with 169 additions and 135 deletions

View File

@ -8,7 +8,7 @@ import {
} from '../../api/types'; } from '../../api/types';
import { ISettings } from '../../types'; import { ISettings } from '../../types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dateFormat'; import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dateFormat';
import { import {
getMediaDuration, getMediaDuration,
@ -65,8 +65,8 @@ interface ISeekMethods {
} }
const AVG_VOICE_DURATION = 30; const AVG_VOICE_DURATION = 30;
const MIN_SPIKES = IS_MOBILE_SCREEN ? 20 : 25; const MIN_SPIKES = IS_SINGLE_COLUMN_LAYOUT ? 20 : 25;
const MAX_SPIKES = IS_MOBILE_SCREEN ? 50 : 75; const MAX_SPIKES = IS_SINGLE_COLUMN_LAYOUT ? 50 : 75;
// This is needed for browsers requiring user interaction before playing. // This is needed for browsers requiring user interaction before playing.
const PRELOAD = true; const PRELOAD = true;
@ -286,7 +286,7 @@ const Audio: FC<OwnProps & StateProps> = ({
)} )}
<Button <Button
round round
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
size={renderingFor ? 'smaller' : 'tiny'} size={renderingFor ? 'smaller' : 'tiny'}
className={buttonClassNames.join(' ')} className={buttonClassNames.join(' ')}
ariaLabel={isPlaying ? 'Pause audio' : 'Play audio'} ariaLabel={isPlaying ? 'Pause audio' : 'Play audio'}

View File

@ -6,7 +6,7 @@ import buildClassName from '../../util/buildClassName';
import { import {
formatMonthAndYear, formatHumanDate, formatTime, formatMonthAndYear, formatHumanDate, formatTime,
} from '../../util/dateFormat'; } from '../../util/dateFormat';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import useLang, { LangFn } from '../../hooks/useLang'; import useLang, { LangFn } from '../../hooks/useLang';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -183,7 +183,7 @@ const CalendarModal: FC<OwnProps> = ({
</Button> </Button>
<h4> <h4>
{formatMonthAndYear(lang, selectedDate, IS_MOBILE_SCREEN)} {formatMonthAndYear(lang, selectedDate, IS_SINGLE_COLUMN_LAYOUT)}
</h4> </h4>
<Button <Button

View File

@ -4,7 +4,7 @@ import React, {
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { MIN_PASSWORD_LENGTH } from '../../config'; import { MIN_PASSWORD_LENGTH } from '../../config';
import { IS_TOUCH_ENV, IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_TOUCH_ENV, IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -23,7 +23,7 @@ type OwnProps = {
onSubmit: (password: string) => void; onSubmit: (password: string) => void;
}; };
const FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400; const FOCUS_DELAY_TIMEOUT_MS = IS_SINGLE_COLUMN_LAYOUT ? 550 : 400;
const PasswordForm: FC<OwnProps> = ({ const PasswordForm: FC<OwnProps> = ({
isLoading = false, isLoading = false,

View File

@ -3,7 +3,7 @@ import React, {
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { STICKER_SIZE_AUTH, STICKER_SIZE_AUTH_MOBILE, STICKER_SIZE_TWO_FA } from '../../config'; import { STICKER_SIZE_AUTH, STICKER_SIZE_AUTH_MOBILE, STICKER_SIZE_TWO_FA } from '../../config';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import getAnimationData from './helpers/animatedAssets'; import getAnimationData from './helpers/animatedAssets';
import AnimatedSticker from './AnimatedSticker'; import AnimatedSticker from './AnimatedSticker';
@ -19,7 +19,7 @@ const PEEK_MONKEY_SHOW_DELAY = 2000;
const SEGMENT_COVER_EYES: [number, number] = [0, 50]; const SEGMENT_COVER_EYES: [number, number] = [0, 50];
const SEGMENT_UNCOVER_EYE: [number, number] = [0, 20]; const SEGMENT_UNCOVER_EYE: [number, number] = [0, 20];
const SEGMENT_COVER_EYE: [number, number] = [20, 0]; const SEGMENT_COVER_EYE: [number, number] = [20, 0];
const STICKER_SIZE = IS_MOBILE_SCREEN ? STICKER_SIZE_AUTH_MOBILE : STICKER_SIZE_AUTH; const STICKER_SIZE = IS_SINGLE_COLUMN_LAYOUT ? STICKER_SIZE_AUTH_MOBILE : STICKER_SIZE_AUTH;
const PasswordMonkey: FC<OwnProps> = ({ isPasswordVisible, isBig }) => { const PasswordMonkey: FC<OwnProps> = ({ isPasswordVisible, isBig }) => {
const [closeMonkeyData, setCloseMonkeyData] = useState<Record<string, any>>(); const [closeMonkeyData, setCloseMonkeyData] = useState<Record<string, any>>();

View File

@ -3,7 +3,7 @@ import React, {
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { STICKER_SIZE_AUTH, STICKER_SIZE_AUTH_MOBILE, STICKER_SIZE_TWO_FA } from '../../config'; import { STICKER_SIZE_AUTH, STICKER_SIZE_AUTH_MOBILE, STICKER_SIZE_TWO_FA } from '../../config';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import getAnimationData from './helpers/animatedAssets'; import getAnimationData from './helpers/animatedAssets';
import AnimatedSticker from './AnimatedSticker'; import AnimatedSticker from './AnimatedSticker';
@ -20,7 +20,7 @@ type OwnProps = {
const TRACKING_START_FRAME = 15; const TRACKING_START_FRAME = 15;
const TRACKING_END_FRAME = 180; const TRACKING_END_FRAME = 180;
const STICKER_SIZE = IS_MOBILE_SCREEN ? STICKER_SIZE_AUTH_MOBILE : STICKER_SIZE_AUTH; const STICKER_SIZE = IS_SINGLE_COLUMN_LAYOUT ? STICKER_SIZE_AUTH_MOBILE : STICKER_SIZE_AUTH;
const TrackingMonkey: FC<OwnProps> = ({ const TrackingMonkey: FC<OwnProps> = ({
code, code,

View File

@ -1,7 +1,7 @@
import { ApiPhoto, ApiVideo, ApiSticker } from '../../../api/types'; import { ApiPhoto, ApiVideo, ApiSticker } from '../../../api/types';
import { getPhotoInlineDimensions, getVideoDimensions, IDimensions } from '../../../modules/helpers'; import { getPhotoInlineDimensions, getVideoDimensions, IDimensions } from '../../../modules/helpers';
import windowSize from '../../../util/windowSize'; import windowSize from '../../../util/windowSize';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { STICKER_SIZE_INLINE_DESKTOP_FACTOR, STICKER_SIZE_INLINE_MOBILE_FACTOR } from '../../../config'; import { STICKER_SIZE_INLINE_DESKTOP_FACTOR, STICKER_SIZE_INLINE_MOBILE_FACTOR } from '../../../config';
export const MEDIA_VIEWER_MEDIA_QUERY = '(max-height: 640px)'; export const MEDIA_VIEWER_MEDIA_QUERY = '(max-height: 640px)';
@ -17,7 +17,7 @@ let cachedMaxWidth: number | undefined;
function getMaxMessageWidthRem(fromOwnMessage: boolean) { function getMaxMessageWidthRem(fromOwnMessage: boolean) {
const regularMaxWidth = fromOwnMessage ? 30 : 29; const regularMaxWidth = fromOwnMessage ? 30 : 29;
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
return regularMaxWidth; return regularMaxWidth;
} }
@ -154,7 +154,11 @@ export function getStickerDimensions(sticker: ApiSticker): IDimensions {
} }
const aspectRatio = (height && width) && height / width; const aspectRatio = (height && width) && height / width;
const baseWidth = (IS_MOBILE_SCREEN ? STICKER_SIZE_INLINE_MOBILE_FACTOR : STICKER_SIZE_INLINE_DESKTOP_FACTOR) * REM; const baseWidth = REM * (
IS_SINGLE_COLUMN_LAYOUT
? STICKER_SIZE_INLINE_MOBILE_FACTOR
: STICKER_SIZE_INLINE_DESKTOP_FACTOR
);
const calculatedHeight = aspectRatio ? baseWidth * aspectRatio : baseWidth; const calculatedHeight = aspectRatio ? baseWidth * aspectRatio : baseWidth;
if (aspectRatio && calculatedHeight > baseWidth) { if (aspectRatio && calculatedHeight > baseWidth) {

View File

@ -6,7 +6,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types'; import { GlobalActions } from '../../global/types';
import { LeftColumnContent, SettingsScreens } from '../../types'; import { LeftColumnContent, SettingsScreens } from '../../types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import captureEscKeyListener from '../../util/captureEscKeyListener'; import captureEscKeyListener from '../../util/captureEscKeyListener';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -240,7 +240,7 @@ const LeftColumn: FC<StateProps & DispatchProps> = ({
return ( return (
<Transition <Transition
id="LeftColumn" id="LeftColumn"
name={IS_MOBILE_SCREEN ? 'slide-layers' : 'push-slide'} name={IS_SINGLE_COLUMN_LAYOUT ? 'slide-layers' : 'push-slide'}
renderCount={RENDER_COUNT} renderCount={RENDER_COUNT}
activeKey={contentType} activeKey={contentType}
> >

View File

@ -11,7 +11,7 @@ import {
} from '../../../api/types'; } from '../../../api/types';
import { ANIMATION_END_DELAY } from '../../../config'; import { ANIMATION_END_DELAY } from '../../../config';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { import {
getChatTitle, getChatTitle,
isChatPrivate, isChatPrivate,
@ -241,7 +241,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
const className = buildClassName( const className = buildClassName(
'Chat chat-item-clickable', 'Chat chat-item-clickable',
isChatPrivate(chatId) ? 'private' : 'group', isChatPrivate(chatId) ? 'private' : 'group',
isSelected && !IS_MOBILE_SCREEN && 'selected', isSelected && !IS_SINGLE_COLUMN_LAYOUT && 'selected',
); );
return ( return (
@ -249,7 +249,7 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
ref={ref} ref={ref}
className={className} className={className}
style={style} style={style}
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
contextActions={contextActions} contextActions={contextActions}
onClick={handleClick} onClick={handleClick}
> >

View File

@ -6,7 +6,7 @@ import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types'; import { GlobalActions } from '../../../global/types';
import { ApiUser } from '../../../api/types'; import { ApiUser } from '../../../api/types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import searchWords from '../../../util/searchWords'; import searchWords from '../../../util/searchWords';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
@ -77,7 +77,7 @@ const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({
key={id} key={id}
className="chat-item-clickable" className="chat-item-clickable"
onClick={() => handleClick(id)} onClick={() => handleClick(id)}
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
> >
<PrivateChatInfo userId={id} forceShowSelf avatarSize="large" /> <PrivateChatInfo userId={id} forceShowSelf avatarSize="large" />
</ListItem> </ListItem>

View File

@ -8,7 +8,7 @@ import { LeftColumnContent, ISettings } from '../../../types';
import { ApiChat } from '../../../api/types'; import { ApiChat } from '../../../api/types';
import { APP_NAME, APP_VERSION, FEEDBACK_URL } from '../../../config'; import { APP_NAME, APP_VERSION, FEEDBACK_URL } from '../../../config';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import { isChatArchived } from '../../../modules/helpers'; import { isChatArchived } from '../../../modules/helpers';
@ -109,7 +109,7 @@ const LeftMainHeader: FC<OwnProps & StateProps & DispatchProps> = ({
return ({ onTrigger, isOpen }) => ( return ({ onTrigger, isOpen }) => (
<Button <Button
round round
ripple={hasMenu && !IS_MOBILE_SCREEN} ripple={hasMenu && !IS_SINGLE_COLUMN_LAYOUT}
size="smaller" size="smaller"
color="translucent" color="translucent"
className={isOpen ? 'active' : ''} className={isOpen ? 'active' : ''}

View File

@ -4,7 +4,7 @@ import React, {
import { LeftColumnContent } from '../../../types'; import { LeftColumnContent } from '../../../types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import Transition from '../../ui/Transition'; import Transition from '../../ui/Transition';
import NewChatStep1 from './NewChatStep1'; import NewChatStep1 from './NewChatStep1';
@ -36,7 +36,7 @@ const NewChat: FC<OwnProps> = ({
return ( return (
<Transition <Transition
id="NewChat" id="NewChat"
name={IS_MOBILE_SCREEN ? 'slide-layers' : 'push-slide'} name={IS_SINGLE_COLUMN_LAYOUT ? 'slide-layers' : 'push-slide'}
renderCount={RENDER_COUNT} renderCount={RENDER_COUNT}
activeKey={content} activeKey={content}
> >

View File

@ -8,7 +8,7 @@ import {
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus,
} from '../../../api/types'; } from '../../../api/types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { import {
getChatTitle, getChatTitle,
getPrivateChatUserId, getPrivateChatUserId,
@ -76,7 +76,7 @@ const ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({
return ( return (
<ListItem <ListItem
className="ChatMessage chat-item-clickable" className="ChatMessage chat-item-clickable"
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
onClick={handleClick} onClick={handleClick}
buttonRef={buttonRef} buttonRef={buttonRef}
> >

View File

@ -7,7 +7,7 @@ import { ApiUser, ApiChat, ApiMessage } from '../../../api/types';
import { GlobalActions } from '../../../global/types'; import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import searchWords from '../../../util/searchWords'; import searchWords from '../../../util/searchWords';
import { unique, pick } from '../../../util/iteratees'; import { unique, pick } from '../../../util/iteratees';
import { getUserFullName, getMessageSummaryText, sortChatIds } from '../../../modules/helpers'; import { getUserFullName, getMessageSummaryText, sortChatIds } from '../../../modules/helpers';
@ -88,7 +88,7 @@ const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({
addRecentlyFoundChatId({ id }); addRecentlyFoundChatId({ id });
} }
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
onReset(); onReset();
} }
}, },

View File

@ -2,7 +2,7 @@ import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import useFoldersReducer from '../../../hooks/reducers/useFoldersReducer'; import useFoldersReducer from '../../../hooks/reducers/useFoldersReducer';
import useTwoFaReducer from '../../../hooks/reducers/useTwoFaReducer'; import useTwoFaReducer from '../../../hooks/reducers/useTwoFaReducer';
@ -213,7 +213,7 @@ const Settings: FC<OwnProps> = ({
return ( return (
<Transition <Transition
id="Settings" id="Settings"
name={IS_MOBILE_SCREEN ? 'slide-layers' : 'push-slide'} name={IS_SINGLE_COLUMN_LAYOUT ? 'slide-layers' : 'push-slide'}
activeKey={currentScreen} activeKey={currentScreen}
renderCount={TRANSITION_RENDER_COUNT} renderCount={TRANSITION_RENDER_COUNT}
> >

View File

@ -6,7 +6,7 @@ import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types'; import { GlobalActions } from '../../../global/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -66,7 +66,7 @@ const SettingsHeader: FC<OwnProps & DispatchProps> = ({
return ({ onTrigger, isOpen }) => ( return ({ onTrigger, isOpen }) => (
<Button <Button
round round
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
size="smaller" size="smaller"
color="translucent" color="translucent"
className={isOpen ? 'active' : ''} className={isOpen ? 'active' : ''}

View File

@ -5,7 +5,7 @@ import { withGlobal } from '../../../../lib/teact/teactn';
import { ApiSticker } from '../../../../api/types'; import { ApiSticker } from '../../../../api/types';
import { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../../../util/environment';
import { selectAnimatedEmoji } from '../../../../modules/selectors'; import { selectAnimatedEmoji } from '../../../../modules/selectors';
import useLang from '../../../../hooks/useLang'; import useLang from '../../../../hooks/useLang';
@ -25,7 +25,7 @@ type StateProps = {
codeLength: number; codeLength: number;
}; };
const FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400; const FOCUS_DELAY_TIMEOUT_MS = IS_SINGLE_COLUMN_LAYOUT ? 550 : 400;
const SettingsTwoFaEmailCode: FC<OwnProps & StateProps> = ({ const SettingsTwoFaEmailCode: FC<OwnProps & StateProps> = ({
animatedEmoji, animatedEmoji,

View File

@ -5,7 +5,7 @@ import { withGlobal } from '../../../../lib/teact/teactn';
import { ApiSticker } from '../../../../api/types'; import { ApiSticker } from '../../../../api/types';
import { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../../../util/environment';
import { selectAnimatedEmoji } from '../../../../modules/selectors'; import { selectAnimatedEmoji } from '../../../../modules/selectors';
import useFlag from '../../../../hooks/useFlag'; import useFlag from '../../../../hooks/useFlag';
import useLang from '../../../../hooks/useLang'; import useLang from '../../../../hooks/useLang';
@ -31,7 +31,7 @@ type StateProps = {
animatedEmoji: ApiSticker; animatedEmoji: ApiSticker;
}; };
const FOCUS_DELAY_TIMEOUT_MS = IS_MOBILE_SCREEN ? 550 : 400; const FOCUS_DELAY_TIMEOUT_MS = IS_SINGLE_COLUMN_LAYOUT ? 550 : 400;
const SettingsTwoFaSkippableForm: FC<OwnProps & StateProps> = ({ const SettingsTwoFaSkippableForm: FC<OwnProps & StateProps> = ({
animatedEmoji, animatedEmoji,

View File

@ -6,7 +6,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types'; import { GlobalActions } from '../../global/types';
import { ApiChat, MAIN_THREAD_ID } from '../../api/types'; import { ApiChat, MAIN_THREAD_ID } from '../../api/types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { import {
getCanPostInChat, getChatTitle, isChatPrivate, sortChatIds, getCanPostInChat, getChatTitle, isChatPrivate, sortChatIds,
} from '../../modules/helpers'; } from '../../modules/helpers';
@ -65,7 +65,7 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
setTimeout(() => { setTimeout(() => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
if (inputRef.current) { if (inputRef.current) {

View File

@ -10,7 +10,7 @@ import {
import { MediaViewerOrigin } from '../../types'; import { MediaViewerOrigin } from '../../types';
import { ANIMATION_END_DELAY } from '../../config'; import { ANIMATION_END_DELAY } from '../../config';
import { IS_IOS, IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../util/environment'; import { IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../util/environment';
import { import {
AVATAR_FULL_DIMENSIONS, AVATAR_FULL_DIMENSIONS,
MEDIA_VIEWER_MEDIA_QUERY, MEDIA_VIEWER_MEDIA_QUERY,
@ -126,6 +126,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
const [isZoomed, setIsZoomed] = useState<boolean>(false); const [isZoomed, setIsZoomed] = useState<boolean>(false);
const [zoomLevel, setZoomLevel] = useState<number>(1); const [zoomLevel, setZoomLevel] = useState<number>(1);
const [panDelta, setPanDelta] = useState({ x: 0, y: 0 }); const [panDelta, setPanDelta] = useState({ x: 0, y: 0 });
const [isFooterHidden, setIsFooterHidden] = useState<boolean>(false);
const messageIds = useMemo(() => { const messageIds = useMemo(() => {
return isWebPagePhoto && messageId return isWebPagePhoto && messageId
@ -189,7 +190,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
const videoDimensions = isVideo ? getVideoDimensions(getMessageVideo(message!)!) : undefined; const videoDimensions = isVideo ? getVideoDimensions(getMessageVideo(message!)!) : undefined;
useEffect(() => { useEffect(() => {
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
return; return;
} }
@ -373,7 +374,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
excludedClosestSelector: `.backdrop, .navigation, .media-viewer-head, .media-viewer-footer${!shouldCloseOnVideo ? ', .VideoPlayer' : ''}`, excludedClosestSelector: `.backdrop, .navigation, .media-viewer-head, .media-viewer-footer${!shouldCloseOnVideo ? ', .VideoPlayer' : ''}`,
onClick: () => { onClick: () => {
if (!isZoomed) { if (!isZoomed && !IS_TOUCH_ENV) {
close(); close();
} }
}, },
@ -382,17 +383,23 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
selectPreviousMedia(); selectPreviousMedia();
} else if (direction === SwipeDirection.Left) { } else if (direction === SwipeDirection.Left) {
selectNextMedia(); selectNextMedia();
} else { } else if (!(e.target && (e.target as HTMLElement).closest('.MediaViewerFooter'))) {
close(); close();
} }
} : undefined, } : undefined,
}); });
}, [close, isGif, isZoomed, selectNextMedia, selectPreviousMedia, canPanZoomWrap]); }, [close, isFooterHidden, isGif, isPhoto, isZoomed, selectNextMedia, selectPreviousMedia]);
const handlePan = useCallback((x: number, y: number) => { const handlePan = useCallback((x: number, y: number) => {
setPanDelta({ x, y }); setPanDelta({ x, y });
}, []); }, []);
const handleToggleFooterVisibility = useCallback(() => {
if (IS_TOUCH_ENV && (isPhoto || isGif)) {
setIsFooterHidden(!isFooterHidden);
}
}, [isFooterHidden, isGif, isPhoto]);
const lang = useLang(); const lang = useLang();
function renderSlide(isActive: boolean) { function renderSlide(isActive: boolean) {
@ -402,7 +409,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
{renderPhoto( {renderPhoto(
fullMediaData || blobUrlPreview, fullMediaData || blobUrlPreview,
calculateMediaViewerDimensions(AVATAR_FULL_DIMENSIONS, false), calculateMediaViewerDimensions(AVATAR_FULL_DIMENSIONS, false),
!IS_MOBILE_SCREEN && !isZoomed, !IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
)} )}
</div> </div>
); );
@ -411,11 +418,15 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
const hasFooter = Boolean(textParts); const hasFooter = Boolean(textParts);
return ( return (
<div key={messageId} className={`media-viewer-content ${hasFooter ? 'has-footer' : ''}`}> <div
key={messageId}
className={`media-viewer-content ${hasFooter ? 'has-footer' : ''}`}
onClick={handleToggleFooterVisibility}
>
{isPhoto && renderPhoto( {isPhoto && renderPhoto(
localBlobUrl || fullMediaData || blobUrlPreview || blobUrlPictogram, localBlobUrl || fullMediaData || blobUrlPreview || blobUrlPictogram,
message && calculateMediaViewerDimensions(photoDimensions!, hasFooter), message && calculateMediaViewerDimensions(photoDimensions!, hasFooter),
!IS_MOBILE_SCREEN && !isZoomed, !IS_SINGLE_COLUMN_LAYOUT && !isZoomed,
)} )}
{isVideo && ( {isVideo && (
<VideoPlayer <VideoPlayer
@ -435,7 +446,8 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
<MediaViewerFooter <MediaViewerFooter
text={textParts} text={textParts}
onClick={handleFooterClick} onClick={handleFooterClick}
isHideable={isVideo} isHidden={isFooterHidden && (!isVideo || isGif)}
isForVideo={isVideo && !isGif}
/> />
)} )}
</div> </div>
@ -465,7 +477,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
{() => ( {() => (
<> <>
<div className="media-viewer-head" dir={lang.isRtl ? 'rtl' : undefined}> <div className="media-viewer-head" dir={lang.isRtl ? 'rtl' : undefined}>
{IS_MOBILE_SCREEN && ( {IS_SINGLE_COLUMN_LAYOUT && (
<Button <Button
className="media-viewer-close" className="media-viewer-close"
round round

View File

@ -2,7 +2,7 @@ import React, { FC, useMemo } from '../../lib/teact/teact';
import { ApiMessage } from '../../api/types'; import { ApiMessage } from '../../api/types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { getMessageMediaHash } from '../../modules/helpers'; import { getMessageMediaHash } from '../../modules/helpers';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -60,7 +60,7 @@ const MediaViewerActions: FC<OwnProps> = ({
); );
}, []); }, []);
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
return ( return (
<div className="MediaViewerActions-mobile"> <div className="MediaViewerActions-mobile">
<DropdownMenu <DropdownMenu

View File

@ -16,7 +16,7 @@
padding-bottom: 4.5rem; padding-bottom: 4.5rem;
background: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0) 100%); background: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0) 100%);
&.hideable { &.is-for-video {
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
@ -44,6 +44,12 @@
} }
} }
&.is-hidden {
.media-viewer-footer-content {
opacity: 0;
}
}
.media-text { .media-text {
margin-bottom: 0; margin-bottom: 0;
overflow: auto; overflow: auto;

View File

@ -1,7 +1,10 @@
import React, { FC, useEffect, useState } from '../../lib/teact/teact'; import React, { FC, useEffect, useState } from '../../lib/teact/teact';
import { throttle } from '../../util/schedulers'; import { throttle } from '../../util/schedulers';
import { TextPart } from '../common/helpers/renderMessageText'; import { TextPart } from '../common/helpers/renderMessageText';
import buildClassName from '../../util/buildClassName';
import { REM } from '../common/helpers/mediaDimensions'; import { REM } from '../common/helpers/mediaDimensions';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import './MediaViewerFooter.scss'; import './MediaViewerFooter.scss';
@ -10,10 +13,13 @@ const RESIZE_THROTTLE_MS = 500;
type OwnProps = { type OwnProps = {
text: TextPart | TextPart[]; text: TextPart | TextPart[];
onClick: () => void; onClick: () => void;
isHideable: boolean; isHidden?: boolean;
isForVideo: boolean;
}; };
const MediaViewerFooter: FC<OwnProps> = ({ text = '', isHideable, onClick }) => { const MediaViewerFooter: FC<OwnProps> = ({
text = '', isHidden, isForVideo, onClick,
}) => {
const [isMultiline, setIsMultiline] = useState(false); const [isMultiline, setIsMultiline] = useState(false);
useEffect(() => { useEffect(() => {
const footerContent = document.querySelector('.MediaViewerFooter .media-text') as HTMLDivElement | null; const footerContent = document.querySelector('.MediaViewerFooter .media-text') as HTMLDivElement | null;
@ -42,10 +48,16 @@ const MediaViewerFooter: FC<OwnProps> = ({ text = '', isHideable, onClick }) =>
} }
} }
const classNames = buildClassName(
'MediaViewerFooter',
isForVideo && 'is-for-video',
isHidden && 'is-hidden',
);
return ( return (
<div className={`MediaViewerFooter ${isHideable ? 'hideable' : ''}`} onClick={stopEvent}> <div className={classNames} onClick={stopEvent}>
{text && ( {text && (
<div className="media-viewer-footer-content" onClick={onClick}> <div className="media-viewer-footer-content" onClick={!IS_SINGLE_COLUMN_LAYOUT ? onClick : undefined}>
<p className={`media-text custom-scroll ${isMultiline ? 'multiline' : ''}`} dir="auto">{text}</p> <p className={`media-text custom-scroll ${isMultiline ? 'multiline' : ''}`} dir="auto">{text}</p>
</div> </div>
)} )}

View File

@ -4,7 +4,7 @@ import React, {
import { IDimensions } from '../../modules/helpers'; import { IDimensions } from '../../modules/helpers';
import { IS_IOS, IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../util/environment'; import { IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../util/environment';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
import useBuffering from '../../hooks/useBuffering'; import useBuffering from '../../hooks/useBuffering';
import useFullscreenStatus from '../../hooks/useFullscreen'; import useFullscreenStatus from '../../hooks/useFullscreen';
@ -144,7 +144,7 @@ const VideoPlayer: FC<OwnProps> = ({
return ( return (
<div <div
className="VideoPlayer" className="VideoPlayer"
onClick={!isGif && IS_MOBILE_SCREEN ? toggleControls : undefined} onClick={!isGif && IS_SINGLE_COLUMN_LAYOUT ? toggleControls : undefined}
onMouseOver={!isGif ? handleMouseOver : undefined} onMouseOver={!isGif ? handleMouseOver : undefined}
onMouseOut={!isGif ? handleMouseOut : undefined} onMouseOut={!isGif ? handleMouseOut : undefined}
> >
@ -164,7 +164,7 @@ const VideoPlayer: FC<OwnProps> = ({
// @ts-ignore // @ts-ignore
style={videoStyle} style={videoStyle}
onEnded={handleEnded} onEnded={handleEnded}
onClick={togglePlayState} onClick={!IS_SINGLE_COLUMN_LAYOUT ? togglePlayState : undefined}
onDoubleClick={handleFullscreenChange} onDoubleClick={handleFullscreenChange}
// eslint-disable-next-line react/jsx-props-no-spreading // eslint-disable-next-line react/jsx-props-no-spreading
{...bufferingHandlers} {...bufferingHandlers}

View File

@ -1,6 +1,6 @@
import React, { FC, useState, useEffect } from '../../lib/teact/teact'; import React, { FC, useState, useEffect } from '../../lib/teact/teact';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { formatMediaDuration } from '../../util/dateFormat'; import { formatMediaDuration } from '../../util/dateFormat';
import formatFileSize from './helpers/formatFileSize'; import formatFileSize from './helpers/formatFileSize';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -58,7 +58,7 @@ const VideoPlayerControls: FC<IProps> = ({
let timeout: number | undefined; let timeout: number | undefined;
if (!isForceVisible) { if (!isForceVisible) {
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
setVisibility(false); setVisibility(false);
} else { } else {
timeout = window.setTimeout(() => { timeout = window.setTimeout(() => {
@ -96,7 +96,7 @@ const VideoPlayerControls: FC<IProps> = ({
<Button <Button
ariaLabel={lang('AccActionPlay')} ariaLabel={lang('AccActionPlay')}
size="tiny" size="tiny"
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
color="translucent-white" color="translucent-white"
className="play" className="play"
onClick={onPlayPause} onClick={onPlayPause}

View File

@ -2,7 +2,7 @@ import React, {
FC, memo, useCallback, useEffect, useRef, useState, FC, memo, useCallback, useEffect, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import usePrevious from '../../hooks/usePrevious'; import usePrevious from '../../hooks/usePrevious';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
@ -82,7 +82,7 @@ const ZoomControls: FC<OwnProps> = ({ isShown, onChangeZoom }) => {
color="translucent-white" color="translucent-white"
ariaLabel={lang('ZoomOut')} ariaLabel={lang('ZoomOut')}
className="zoom-out" className="zoom-out"
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
onClick={handleZoomOut} onClick={handleZoomOut}
> >
<i className="icon-zoom-out" /> <i className="icon-zoom-out" />
@ -93,7 +93,7 @@ const ZoomControls: FC<OwnProps> = ({ isShown, onChangeZoom }) => {
color="translucent-white" color="translucent-white"
ariaLabel="Zoom In" ariaLabel="Zoom In"
className="zoom-in" className="zoom-in"
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
onClick={handleZoomIn} onClick={handleZoomIn}
> >
<i className="icon-zoom-in" /> <i className="icon-zoom-in" />

View File

@ -6,7 +6,7 @@ import {
ApiAudio, ApiChat, ApiMessage, ApiUser, ApiAudio, ApiChat, ApiMessage, ApiUser,
} from '../../api/types'; } from '../../api/types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import * as mediaLoader from '../../util/mediaLoader'; import * as mediaLoader from '../../util/mediaLoader';
import { import {
getMediaDuration, getMessageAudio, getMessageKey, getMessageMediaHash, getSenderTitle, getMediaDuration, getMessageAudio, getMessageKey, getMessageMediaHash, getSenderTitle,
@ -67,7 +67,7 @@ const AudioPlayer: FC<OwnProps & StateProps & DispatchProps> = ({
<div className={buildClassName('AudioPlayer', className)} dir={lang.isRtl ? 'rtl' : undefined}> <div className={buildClassName('AudioPlayer', className)} dir={lang.isRtl ? 'rtl' : undefined}>
<Button <Button
round round
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
color="translucent" color="translucent"
size="smaller" size="smaller"
className={buildClassName('toggle-play', isPlaying ? 'pause' : 'play')} className={buildClassName('toggle-play', isPlaying ? 'pause' : 'play')}

View File

@ -11,7 +11,7 @@ import { GlobalActions, MessageListType } from '../../global/types';
import { MAIN_THREAD_ID } from '../../api/types'; import { MAIN_THREAD_ID } from '../../api/types';
import { IAnchorPosition } from '../../types'; import { IAnchorPosition } from '../../types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import { isChatChannel, isChatSuperGroup } from '../../modules/helpers'; import { isChatChannel, isChatSuperGroup } from '../../modules/helpers';
import { import {
@ -94,7 +94,7 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
const handleSearchClick = useCallback(() => { const handleSearchClick = useCallback(() => {
openLocalTextSearch(); openLocalTextSearch();
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
// iOS requires synchronous focus on user event. // iOS requires synchronous focus on user event.
const searchInput = document.querySelector<HTMLInputElement>('#MobileSearch input')!; const searchInput = document.querySelector<HTMLInputElement>('#MobileSearch input')!;
searchInput.focus(); searchInput.focus();
@ -112,7 +112,7 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
return ( return (
<div className="HeaderActions"> <div className="HeaderActions">
{!IS_MOBILE_SCREEN && canSubscribe && ( {!IS_SINGLE_COLUMN_LAYOUT && canSubscribe && (
<Button <Button
size="tiny" size="tiny"
ripple ripple
@ -122,7 +122,7 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
{lang(isChannel ? 'Subscribe' : 'Join Group')} {lang(isChannel ? 'Subscribe' : 'Join Group')}
</Button> </Button>
)} )}
{!IS_MOBILE_SCREEN && canStartBot && ( {!IS_SINGLE_COLUMN_LAYOUT && canStartBot && (
<Button <Button
size="tiny" size="tiny"
ripple ripple
@ -132,7 +132,7 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
{lang('Start')} {lang('Start')}
</Button> </Button>
)} )}
{!IS_MOBILE_SCREEN && canSearch && ( {!IS_SINGLE_COLUMN_LAYOUT && canSearch && (
<Button <Button
round round
ripple={isRightColumnShown} ripple={isRightColumnShown}
@ -144,12 +144,12 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
<i className="icon-search" /> <i className="icon-search" />
</Button> </Button>
)} )}
{(IS_MOBILE_SCREEN || !canSubscribe) && ( {(IS_SINGLE_COLUMN_LAYOUT || !canSubscribe) && (
<Button <Button
ref={menuButtonRef} ref={menuButtonRef}
className={isMenuOpen ? 'active' : ''} className={isMenuOpen ? 'active' : ''}
round round
ripple={!IS_MOBILE_SCREEN} ripple={!IS_SINGLE_COLUMN_LAYOUT}
size="smaller" size="smaller"
color="translucent" color="translucent"
disabled={noMenu} disabled={noMenu}
@ -207,8 +207,8 @@ export default memo(withGlobal<OwnProps>(
const canLeave = isMainThread && !canSubscribe; const canLeave = isMainThread && !canSubscribe;
const noMenu = !( const noMenu = !(
(IS_MOBILE_SCREEN && canSubscribe) (IS_SINGLE_COLUMN_LAYOUT && canSubscribe)
|| (IS_MOBILE_SCREEN && canSearch) || (IS_SINGLE_COLUMN_LAYOUT && canSearch)
|| canMute || canMute
|| canSelect || canSelect
|| canLeave || canLeave

View File

@ -7,7 +7,7 @@ import { GlobalActions } from '../../global/types';
import { ApiChat } from '../../api/types'; import { ApiChat } from '../../api/types';
import { IAnchorPosition } from '../../types'; import { IAnchorPosition } from '../../types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { disableScrolling, enableScrolling } from '../../util/scrollLock'; import { disableScrolling, enableScrolling } from '../../util/scrollLock';
import { selectChat } from '../../modules/selectors'; import { selectChat } from '../../modules/selectors';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -127,7 +127,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({
style={`left: ${x}px;top: ${y}px;`} style={`left: ${x}px;top: ${y}px;`}
onClose={closeMenu} onClose={closeMenu}
> >
{IS_MOBILE_SCREEN && canSubscribe && ( {IS_SINGLE_COLUMN_LAYOUT && canSubscribe && (
<MenuItem <MenuItem
icon={isChannel ? 'channel' : 'group'} icon={isChannel ? 'channel' : 'group'}
onClick={handleSubscribe} onClick={handleSubscribe}
@ -135,7 +135,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({
{lang(isChannel ? 'Subscribe' : 'Join Group')} {lang(isChannel ? 'Subscribe' : 'Join Group')}
</MenuItem> </MenuItem>
)} )}
{IS_MOBILE_SCREEN && canSearch && ( {IS_SINGLE_COLUMN_LAYOUT && canSearch && (
<MenuItem <MenuItem
icon="search" icon="search"
onClick={handleSearch} onClick={handleSearch}

View File

@ -8,7 +8,7 @@ import { GlobalActions, MessageListType } from '../../global/types';
import { LoadMoreDirection } from '../../types'; import { LoadMoreDirection } from '../../types';
import { ANIMATION_END_DELAY, MESSAGE_LIST_SLICE, SCHEDULED_WHEN_ONLINE } from '../../config'; import { ANIMATION_END_DELAY, MESSAGE_LIST_SLICE, SCHEDULED_WHEN_ONLINE } from '../../config';
import { IS_ANDROID, IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_ANDROID, IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { import {
selectChatMessages, selectChatMessages,
selectIsViewportNewest, selectIsViewportNewest,
@ -102,7 +102,7 @@ const UNREAD_DIVIDER_TOP = 10;
const UNREAD_DIVIDER_TOP_WITH_TOOLS = 60; const UNREAD_DIVIDER_TOP_WITH_TOOLS = 60;
const SCROLL_DEBOUNCE = 200; const SCROLL_DEBOUNCE = 200;
const INTERSECTION_THROTTLE_FOR_MEDIA = IS_ANDROID ? 1000 : 350; const INTERSECTION_THROTTLE_FOR_MEDIA = IS_ANDROID ? 1000 : 350;
const INTERSECTION_MARGIN_FOR_MEDIA = IS_MOBILE_SCREEN ? 300 : 500; const INTERSECTION_MARGIN_FOR_MEDIA = IS_SINGLE_COLUMN_LAYOUT ? 300 : 500;
const FOCUSING_DURATION = 1000; const FOCUSING_DURATION = 1000;
const BOTTOM_FOCUS_MARGIN = 20; const BOTTOM_FOCUS_MARGIN = 20;
const SELECT_MODE_ANIMATION_DURATION = 200; const SELECT_MODE_ANIMATION_DURATION = 200;

View File

@ -19,7 +19,7 @@ import {
DARK_THEME_BG_COLOR, DARK_THEME_BG_COLOR,
LIGHT_THEME_BG_COLOR, LIGHT_THEME_BG_COLOR,
} from '../../config'; } from '../../config';
import { IS_MOBILE_SCREEN, IS_TOUCH_ENV, MASK_IMAGE_DISABLED } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV, MASK_IMAGE_DISABLED } from '../../util/environment';
import { DropAreaState } from './composer/DropArea'; import { DropAreaState } from './composer/DropArea';
import { import {
selectChat, selectChat,
@ -76,7 +76,7 @@ type StateProps = {
type DispatchProps = Pick<GlobalActions, 'openChat' | 'unpinAllMessages' | 'loadUser'>; type DispatchProps = Pick<GlobalActions, 'openChat' | 'unpinAllMessages' | 'loadUser'>;
const CLOSE_ANIMATION_DURATION = IS_MOBILE_SCREEN ? 450 + ANIMATION_END_DELAY : undefined; const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
function canBeQuicklyUploaded(item: DataTransferItem) { function canBeQuicklyUploaded(item: DataTransferItem) {
return item.kind === 'file' && item.type && CONTENT_TYPES_FOR_QUICK_UPLOAD.includes(item.type); return item.kind === 'file' && item.type && CONTENT_TYPES_FOR_QUICK_UPLOAD.includes(item.type);
@ -308,7 +308,7 @@ const MiddleColumn: FC<StateProps & DispatchProps> = ({
canPost={renderingCanPost} canPost={renderingCanPost}
/> />
</div> </div>
{IS_MOBILE_SCREEN && <MobileSearch isActive={Boolean(isMobileSearchActive)} />} {IS_SINGLE_COLUMN_LAYOUT && <MobileSearch isActive={Boolean(isMobileSearchActive)} />}
</> </>
)} )}
{chatId && ( {chatId && (
@ -341,7 +341,7 @@ export default memo(withGlobal(
patternColor, patternColor,
isRightColumnShown: selectIsRightColumnShown(global), isRightColumnShown: selectIsRightColumnShown(global),
isBackgroundBlurred, isBackgroundBlurred,
isMobileSearchActive: Boolean(IS_MOBILE_SCREEN && selectCurrentTextSearch(global)), isMobileSearchActive: Boolean(IS_SINGLE_COLUMN_LAYOUT && selectCurrentTextSearch(global)),
isSelectModeActive: selectIsInSelectMode(global), isSelectModeActive: selectIsInSelectMode(global),
animationLevel: global.settings.byKey.animationLevel, animationLevel: global.settings.byKey.animationLevel,
}; };
@ -365,7 +365,7 @@ export default memo(withGlobal(
threadId, threadId,
messageListType, messageListType,
isPrivate: isChatPrivate(chatId), isPrivate: isChatPrivate(chatId),
canPost: !isPinnedMessageList && (!chat || canPost) && (!isBotNotStarted || IS_MOBILE_SCREEN), canPost: !isPinnedMessageList && (!chat || canPost) && (!isBotNotStarted || IS_SINGLE_COLUMN_LAYOUT),
isPinnedMessageList, isPinnedMessageList,
messageSendingRestrictionReason: chat && getMessageSendingRestrictionReason(chat), messageSendingRestrictionReason: chat && getMessageSendingRestrictionReason(chat),
hasPinnedOrAudioMessage: ( hasPinnedOrAudioMessage: (

View File

@ -21,7 +21,7 @@ import {
SAFE_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN, SAFE_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN,
SAFE_SCREEN_WIDTH_FOR_CHAT_INFO, SAFE_SCREEN_WIDTH_FOR_CHAT_INFO,
} from '../../config'; } from '../../config';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { import {
isChatPrivate, isChatPrivate,
isChatArchived, isChatArchived,
@ -184,14 +184,14 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
}, [openChat, chatId]); }, [openChat, chatId]);
const handleBackClick = useCallback(() => { const handleBackClick = useCallback(() => {
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
const messageInput = document.getElementById(EDITABLE_INPUT_ID); const messageInput = document.getElementById(EDITABLE_INPUT_ID);
if (messageInput) { if (messageInput) {
messageInput.blur(); messageInput.blur();
} }
} }
if (threadId === MAIN_THREAD_ID && messageListType === 'thread') { if (threadId === MAIN_THREAD_ID && messageListType === 'thread') {
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
openChat({ id: undefined }); openChat({ id: undefined });
} else { } else {
toggleLeftColumn(); toggleLeftColumn();

View File

@ -19,7 +19,7 @@ import {
import { LangCode } from '../../../types'; import { LangCode } from '../../../types';
import { EDITABLE_INPUT_ID, SCHEDULED_WHEN_ONLINE } from '../../../config'; import { EDITABLE_INPUT_ID, SCHEDULED_WHEN_ONLINE } from '../../../config';
import { IS_VOICE_RECORDING_SUPPORTED, IS_MOBILE_SCREEN, IS_EMOJI_SUPPORTED } from '../../../util/environment'; import { IS_VOICE_RECORDING_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT, IS_EMOJI_SUPPORTED } from '../../../util/environment';
import { import {
selectChat, selectChat,
selectIsChatWithBot, selectIsChatWithBot,
@ -337,7 +337,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
setHtml(`${htmlRef.current!}${newHtml}`); setHtml(`${htmlRef.current!}${newHtml}`);
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
// If selection is outside of input, set cursor at the end of input // If selection is outside of input, set cursor at the end of input
requestAnimationFrame(() => { requestAnimationFrame(() => {
focusEditableElement(messageInput); focusEditableElement(messageInput);
@ -368,7 +368,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
closeMentionTooltip(); closeMentionTooltip();
closeEmojiTooltip(); closeEmojiTooltip();
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
// @perf // @perf
setTimeout(() => closeSymbolMenu(), SENDING_ANIMATION_DURATION); setTimeout(() => closeSymbolMenu(), SENDING_ANIMATION_DURATION);
} else { } else {
@ -582,7 +582,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
const handleSymbolMenuOpen = useCallback(() => { const handleSymbolMenuOpen = useCallback(() => {
const messageInput = document.getElementById(EDITABLE_INPUT_ID)!; const messageInput = document.getElementById(EDITABLE_INPUT_ID)!;
if (!IS_MOBILE_SCREEN || messageInput !== document.activeElement) { if (!IS_SINGLE_COLUMN_LAYOUT || messageInput !== document.activeElement) {
openSymbolMenu(); openSymbolMenu();
return; return;
} }
@ -598,7 +598,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
}, [openChat, chatId, threadId]); }, [openChat, chatId, threadId]);
useEffect(() => { useEffect(() => {
if (isRightColumnShown && IS_MOBILE_SCREEN) { if (isRightColumnShown && IS_SINGLE_COLUMN_LAYOUT) {
closeSymbolMenu(); closeSymbolMenu();
} }
}, [isRightColumnShown, closeSymbolMenu]); }, [isRightColumnShown, closeSymbolMenu]);
@ -751,7 +751,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
disabled={!allowedAttachmentOptions.canAttachEmbedLinks} disabled={!allowedAttachmentOptions.canAttachEmbedLinks}
/> />
<div className="message-input-wrapper"> <div className="message-input-wrapper">
{IS_MOBILE_SCREEN ? ( {IS_SINGLE_COLUMN_LAYOUT ? (
<Button <Button
className={symbolMenuButtonClassName} className={symbolMenuButtonClassName}
round round
@ -782,7 +782,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
activeVoiceRecording && window.innerWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER ? '' : lang('Message') activeVoiceRecording && window.innerWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER ? '' : lang('Message')
} }
shouldSetFocus={isSymbolMenuOpen} shouldSetFocus={isSymbolMenuOpen}
shouldSupressFocus={IS_MOBILE_SCREEN && isSymbolMenuOpen} shouldSupressFocus={IS_SINGLE_COLUMN_LAYOUT && isSymbolMenuOpen}
shouldSupressTextFormatter={isEmojiTooltipOpen || isMentionTooltipOpen} shouldSupressTextFormatter={isEmojiTooltipOpen || isMentionTooltipOpen}
onUpdate={setHtml} onUpdate={setHtml}
onSend={onSend} onSend={onSend}

View File

@ -1,6 +1,6 @@
import React, { FC, memo, useRef } from '../../../lib/teact/teact'; import React, { FC, memo, useRef } from '../../../lib/teact/teact';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import windowSize from '../../../util/windowSize'; import windowSize from '../../../util/windowSize';
import { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver'; import { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';
@ -35,7 +35,7 @@ const EmojiCategory: FC<OwnProps> = ({
const lang = useLang(); const lang = useLang();
const emojisPerRow = IS_MOBILE_SCREEN const emojisPerRow = IS_SINGLE_COLUMN_LAYOUT
? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (EMOJI_SIZE + EMOJI_MARGIN)) ? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (EMOJI_SIZE + EMOJI_MARGIN))
: EMOJIS_PER_ROW_ON_DESKTOP; : EMOJIS_PER_ROW_ON_DESKTOP;
const height = Math.ceil(category.emojis.length / emojisPerRow) * (EMOJI_SIZE + EMOJI_MARGIN); const height = Math.ceil(category.emojis.length / emojisPerRow) * (EMOJI_SIZE + EMOJI_MARGIN);

View File

@ -7,7 +7,7 @@ import { GlobalState } from '../../../global/types';
import { MENU_TRANSITION_DURATION } from '../../../config'; import { MENU_TRANSITION_DURATION } from '../../../config';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { import {
EmojiModule, EmojiModule,
EmojiRawData, EmojiRawData,
@ -99,7 +99,7 @@ const EmojiPicker: FC<OwnProps & StateProps> = ({
setActiveCategoryIndex(intersectingWithIndexes[Math.floor(intersectingWithIndexes.length / 2)].index); setActiveCategoryIndex(intersectingWithIndexes[Math.floor(intersectingWithIndexes.length / 2)].index);
}); });
useHorizontalScroll(headerRef.current, !IS_MOBILE_SCREEN); useHorizontalScroll(headerRef.current, !IS_SINGLE_COLUMN_LAYOUT);
// Scroll header when active set updates // Scroll header when active set updates
useEffect(() => { useEffect(() => {

View File

@ -14,7 +14,7 @@ import focusEditableElement from '../../../util/focusEditableElement';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
import { import {
IS_ANDROID, IS_IOS, IS_MOBILE_SCREEN, IS_TOUCH_ENV, IS_ANDROID, IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV,
} from '../../../util/environment'; } from '../../../util/environment';
import captureKeyboardListeners from '../../../util/captureKeyboardListeners'; import captureKeyboardListeners from '../../../util/captureKeyboardListeners';
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps'; import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
@ -52,7 +52,7 @@ type StateProps = {
type DispatchProps = Pick<GlobalActions, 'editLastMessage' | 'replyToNextMessage'>; type DispatchProps = Pick<GlobalActions, 'editLastMessage' | 'replyToNextMessage'>;
const MAX_INPUT_HEIGHT = IS_MOBILE_SCREEN ? 256 : 416; const MAX_INPUT_HEIGHT = IS_SINGLE_COLUMN_LAYOUT ? 256 : 416;
const TAB_INDEX_PRIORITY_TIMEOUT = 2000; const TAB_INDEX_PRIORITY_TIMEOUT = 2000;
const TEXT_FORMATTER_SAFE_AREA_PX = 90; const TEXT_FORMATTER_SAFE_AREA_PX = 90;
// For some reason Safari inserts `<br>` after user removes text from input // For some reason Safari inserts `<br>` after user removes text from input

View File

@ -5,7 +5,7 @@ import { StickerSetOrRecent } from '../../../types';
import { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver'; import { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';
import { STICKER_SIZE_PICKER } from '../../../config'; import { STICKER_SIZE_PICKER } from '../../../config';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import windowSize from '../../../util/windowSize'; import windowSize from '../../../util/windowSize';
import StickerButton from '../../common/StickerButton'; import StickerButton from '../../common/StickerButton';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
@ -22,7 +22,7 @@ type OwnProps = {
}; };
const STICKERS_PER_ROW_ON_DESKTOP = 5; const STICKERS_PER_ROW_ON_DESKTOP = 5;
const STICKER_MARGIN = IS_MOBILE_SCREEN ? 8 : 16; const STICKER_MARGIN = IS_SINGLE_COLUMN_LAYOUT ? 8 : 16;
const MOBILE_CONTAINER_PADDING = 8; const MOBILE_CONTAINER_PADDING = 8;
const StickerSet: FC<OwnProps> = ({ const StickerSet: FC<OwnProps> = ({
@ -41,7 +41,7 @@ const StickerSet: FC<OwnProps> = ({
const { transitionClassNames } = useShowTransition(shouldRender, undefined, undefined, 'slow'); const { transitionClassNames } = useShowTransition(shouldRender, undefined, undefined, 'slow');
const stickersPerRow = IS_MOBILE_SCREEN const stickersPerRow = IS_SINGLE_COLUMN_LAYOUT
? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (STICKER_SIZE_PICKER + STICKER_MARGIN)) ? Math.floor((windowSize.get().width - MOBILE_CONTAINER_PADDING) / (STICKER_SIZE_PICKER + STICKER_MARGIN))
: STICKERS_PER_ROW_ON_DESKTOP; : STICKERS_PER_ROW_ON_DESKTOP;
const height = Math.ceil(stickerSet.count / stickersPerRow) * (STICKER_SIZE_PICKER + STICKER_MARGIN); const height = Math.ceil(stickerSet.count / stickersPerRow) * (STICKER_SIZE_PICKER + STICKER_MARGIN);

View File

@ -5,7 +5,7 @@ import React, {
import { ApiSticker, ApiVideo } from '../../../api/types'; import { ApiSticker, ApiVideo } from '../../../api/types';
import { IAllowedAttachmentOptions } from '../../../modules/helpers'; import { IAllowedAttachmentOptions } from '../../../modules/helpers';
import { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../../util/environment';
import { fastRaf } from '../../../util/schedulers'; import { fastRaf } from '../../../util/schedulers';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
@ -49,7 +49,7 @@ const SymbolMenu: FC<OwnProps> = ({
const [activeTab, setActiveTab] = useState<number>(0); const [activeTab, setActiveTab] = useState<number>(0);
const [recentEmojis, setRecentEmojis] = useState<string[]>([]); const [recentEmojis, setRecentEmojis] = useState<string[]>([]);
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose, undefined, IS_MOBILE_SCREEN); const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose, undefined, IS_SINGLE_COLUMN_LAYOUT);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);
if (!isActivated && isOpen) { if (!isActivated && isOpen) {
@ -61,7 +61,7 @@ const SymbolMenu: FC<OwnProps> = ({
}, [onLoad]); }, [onLoad]);
useLayoutEffect(() => { useLayoutEffect(() => {
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
return undefined; return undefined;
} }
@ -158,7 +158,7 @@ const SymbolMenu: FC<OwnProps> = ({
</Transition> </Transition>
)} )}
</div> </div>
{IS_MOBILE_SCREEN && ( {IS_SINGLE_COLUMN_LAYOUT && (
<Button <Button
round round
faded faded
@ -180,7 +180,7 @@ const SymbolMenu: FC<OwnProps> = ({
</> </>
); );
if (IS_MOBILE_SCREEN) { if (IS_SINGLE_COLUMN_LAYOUT) {
if (!shouldRender) { if (!shouldRender) {
return undefined; return undefined;
} }

View File

@ -3,7 +3,7 @@ import {
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { EDITABLE_INPUT_ID } from '../../../../config'; import { EDITABLE_INPUT_ID } from '../../../../config';
import { IS_MOBILE_SCREEN } from '../../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../../util/environment';
import { import {
EmojiData, EmojiModule, EmojiRawData, uncompressEmoji, EmojiData, EmojiModule, EmojiRawData, uncompressEmoji,
} from '../../../../util/emoji'; } from '../../../../util/emoji';
@ -154,7 +154,7 @@ export default function useEmojiTooltip(
if (atIndex !== -1) { if (atIndex !== -1) {
onUpdateHtml(`${html.substr(0, atIndex)}${textEmoji}`); onUpdateHtml(`${html.substr(0, atIndex)}${textEmoji}`);
const messageInput = document.getElementById(inputId)!; const messageInput = document.getElementById(inputId)!;
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
focusEditableElement(messageInput, true); focusEditableElement(messageInput, true);
}); });

View File

@ -4,7 +4,7 @@ import { ApiMessageEntityTypes, ApiChatMember, ApiUser } from '../../../../api/t
import { EDITABLE_INPUT_ID } from '../../../../config'; import { EDITABLE_INPUT_ID } from '../../../../config';
import { getUserFirstOrLastName } from '../../../../modules/helpers'; import { getUserFirstOrLastName } from '../../../../modules/helpers';
import searchUserName from '../helpers/searchUserName'; import searchUserName from '../helpers/searchUserName';
import { IS_MOBILE_SCREEN } from '../../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../../util/environment';
import focusEditableElement from '../../../../util/focusEditableElement'; import focusEditableElement from '../../../../util/focusEditableElement';
import useFlag from '../../../../hooks/useFlag'; import useFlag from '../../../../hooks/useFlag';
@ -80,7 +80,7 @@ export default function useMentionTooltip(
if (atIndex !== -1) { if (atIndex !== -1) {
onUpdateHtml(`${html.substr(0, atIndex)}${insertedHtml}&nbsp;`); onUpdateHtml(`${html.substr(0, atIndex)}${insertedHtml}&nbsp;`);
const messageInput = document.getElementById(inputId)!; const messageInput = document.getElementById(inputId)!;
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
focusEditableElement(messageInput, forceFocus); focusEditableElement(messageInput, forceFocus);
}); });

View File

@ -1,6 +1,6 @@
import { ApiMessage } from '../../../../api/types'; import { ApiMessage } from '../../../../api/types';
import { IS_CANVAS_FILTER_SUPPORTED, IS_MOBILE_SCREEN } from '../../../../util/environment'; import { IS_CANVAS_FILTER_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT } from '../../../../util/environment';
import { getMessageMediaThumbDataUri } from '../../../../modules/helpers'; import { getMessageMediaThumbDataUri } from '../../../../modules/helpers';
import useCanvasBlur from '../../../../hooks/useCanvasBlur'; import useCanvasBlur from '../../../../hooks/useCanvasBlur';
@ -8,6 +8,6 @@ export default function useBlurredMediaThumbRef(message: ApiMessage, fullMediaDa
return useCanvasBlur( return useCanvasBlur(
getMessageMediaThumbDataUri(message), getMessageMediaThumbDataUri(message),
Boolean(fullMediaData), Boolean(fullMediaData),
IS_MOBILE_SCREEN && !IS_CANVAS_FILTER_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT && !IS_CANVAS_FILTER_SUPPORTED,
); );
} }

View File

@ -6,7 +6,7 @@ import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types'; import { GlobalActions } from '../../global/types';
import { ManagementScreens, ProfileState } from '../../types'; import { ManagementScreens, ProfileState } from '../../types';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { debounce } from '../../util/schedulers'; import { debounce } from '../../util/schedulers';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
@ -270,7 +270,7 @@ const RightHeader: FC<OwnProps & StateProps & DispatchProps> = ({
} }
const isBackButton = ( const isBackButton = (
IS_MOBILE_SCREEN IS_SINGLE_COLUMN_LAYOUT
|| contentKey === HeaderContent.SharedMedia || contentKey === HeaderContent.SharedMedia
|| contentKey === HeaderContent.MemberList || contentKey === HeaderContent.MemberList
|| isManagement || isManagement

View File

@ -5,7 +5,7 @@ import React, {
import { withGlobal } from '../../lib/teact/teactn'; import { withGlobal } from '../../lib/teact/teactn';
import { ANIMATION_END_DELAY } from '../../config'; import { ANIMATION_END_DELAY } from '../../config';
import { IS_MOBILE_SCREEN } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import useForceUpdate from '../../hooks/useForceUpdate'; import useForceUpdate from '../../hooks/useForceUpdate';
import usePrevious from '../../hooks/usePrevious'; import usePrevious from '../../hooks/usePrevious';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
@ -44,7 +44,7 @@ const ANIMATION_DURATION = {
'zoom-fade': 150, 'zoom-fade': 150,
'scroll-slide': 500, 'scroll-slide': 500,
fade: 150, fade: 150,
'slide-layers': IS_MOBILE_SCREEN ? 450 : 300, 'slide-layers': IS_SINGLE_COLUMN_LAYOUT ? 450 : 300,
'push-slide': 300, 'push-slide': 300,
reveal: 350, reveal: 350,
}; };

View File

@ -14,7 +14,7 @@ import {
LEGACY_SESSION_KEY, LEGACY_SESSION_KEY,
MIN_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN, GLOBAL_STATE_CACHE_USER_LIST_LIMIT, SESSION_USER_KEY, MIN_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN, GLOBAL_STATE_CACHE_USER_LIST_LIMIT, SESSION_USER_KEY,
} from '../config'; } from '../config';
import { IS_MOBILE_SCREEN } from '../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../util/environment';
import { pick } from '../util/iteratees'; import { pick } from '../util/iteratees';
import { INITIAL_STATE } from './initial'; import { INITIAL_STATE } from './initial';
import { selectCurrentMessageList } from '../modules/selectors'; import { selectCurrentMessageList } from '../modules/selectors';
@ -205,7 +205,7 @@ function reduceMessages(global: GlobalState): GlobalState['messages'] {
return { return {
byChatId, byChatId,
messageLists: !currentMessageList || IS_MOBILE_SCREEN ? undefined : [{ messageLists: !currentMessageList || IS_SINGLE_COLUMN_LAYOUT ? undefined : [{
...currentMessageList, ...currentMessageList,
threadId: MAIN_THREAD_ID, threadId: MAIN_THREAD_ID,
type: 'thread', type: 'thread',

View File

@ -2,7 +2,7 @@ import { RefObject } from 'react';
import { useState, useEffect, useCallback } from '../lib/teact/teact'; import { useState, useEffect, useCallback } from '../lib/teact/teact';
import { IAnchorPosition } from '../types'; import { IAnchorPosition } from '../types';
import { IS_TOUCH_ENV, IS_MOBILE_SCREEN } from '../util/environment'; import { IS_TOUCH_ENV, IS_SINGLE_COLUMN_LAYOUT } from '../util/environment';
const LONG_TAP_DURATION_MS = 250; const LONG_TAP_DURATION_MS = 250;
const SELECTION_ANIMATION_DURATION_MS = 200; const SELECTION_ANIMATION_DURATION_MS = 200;
@ -10,7 +10,7 @@ const SELECTION_ANIMATION_DURATION_MS = 200;
let contextMenuCounter = 0; let contextMenuCounter = 0;
function checkIsDisabledForMobile() { function checkIsDisabledForMobile() {
return IS_MOBILE_SCREEN return IS_SINGLE_COLUMN_LAYOUT
&& window.document.body.classList.contains('enable-symbol-menu-transforms'); && window.document.body.classList.contains('enable-symbol-menu-transforms');
} }

View File

@ -2,7 +2,7 @@ import Worker from 'worker-loader!./rlottie.worker';
import { import {
DPR, DPR,
IS_MOBILE_SCREEN, IS_SINGLE_COLUMN_LAYOUT,
IS_SAFARI, IS_SAFARI,
} from '../../util/environment'; } from '../../util/environment';
import WorkerConnector from '../../util/WorkerConnector'; import WorkerConnector from '../../util/WorkerConnector';
@ -22,7 +22,7 @@ type Chunks = (Frames | undefined)[];
// TODO Consider removing chunks // TODO Consider removing chunks
const CHUNK_SIZE = 1; const CHUNK_SIZE = 1;
const MAX_WORKERS = 4; const MAX_WORKERS = 4;
const HIGH_PRIORITY_QUALITY = IS_MOBILE_SCREEN ? 0.75 : 1; const HIGH_PRIORITY_QUALITY = IS_SINGLE_COLUMN_LAYOUT ? 0.75 : 1;
const LOW_PRIORITY_QUALITY = 0.75; const LOW_PRIORITY_QUALITY = 0.75;
const HIGH_PRIORITY_MAX_FPS = 60; const HIGH_PRIORITY_MAX_FPS = 60;
const LOW_PRIORITY_MAX_FPS = 30; const LOW_PRIORITY_MAX_FPS = 30;

View File

@ -2,7 +2,7 @@ import { addReducer } from '../../../lib/teact/teactn';
import { GlobalState } from '../../../global/types'; import { GlobalState } from '../../../global/types';
import { IS_MOBILE_SCREEN } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import getReadableErrorText from '../../../util/getReadableErrorText'; import getReadableErrorText from '../../../util/getReadableErrorText';
import { selectCurrentMessageList } from '../../selectors'; import { selectCurrentMessageList } from '../../selectors';
@ -58,7 +58,7 @@ addReducer('closeManagement', (global): GlobalState | undefined => {
}); });
addReducer('openChat', (global, actions, payload) => { addReducer('openChat', (global, actions, payload) => {
if (!IS_MOBILE_SCREEN) { if (!IS_SINGLE_COLUMN_LAYOUT) {
return undefined; return undefined;
} }

View File

@ -1,7 +1,7 @@
import { GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { RightColumnContent } from '../../types'; import { RightColumnContent } from '../../types';
import { IS_MOBILE_SCREEN, SYSTEM_THEME } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, SYSTEM_THEME } from '../../util/environment';
import { selectCurrentMessageList, selectIsPollResultsOpen } from './messages'; import { selectCurrentMessageList, selectIsPollResultsOpen } from './messages';
import { selectCurrentTextSearch } from './localSearch'; import { selectCurrentTextSearch } from './localSearch';
import { selectCurrentStickerSearch, selectCurrentGifSearch } from './symbols'; import { selectCurrentStickerSearch, selectCurrentGifSearch } from './symbols';
@ -20,7 +20,7 @@ export function selectRightColumnContentKey(global: GlobalState) {
} = global; } = global;
const isPollResults = selectIsPollResultsOpen(global); const isPollResults = selectIsPollResultsOpen(global);
const isSearch = Boolean(!IS_MOBILE_SCREEN && selectCurrentTextSearch(global)); const isSearch = Boolean(!IS_SINGLE_COLUMN_LAYOUT && selectCurrentTextSearch(global));
const isManagement = selectCurrentManagement(global); const isManagement = selectCurrentManagement(global);
const stickerSearch = selectCurrentStickerSearch(global); const stickerSearch = selectCurrentStickerSearch(global);
const isStickerSearch = stickerSearch.query !== undefined; const isStickerSearch = stickerSearch.query !== undefined;

View File

@ -35,7 +35,7 @@ export const IS_SAFARI = /^((?!chrome|android).)*safari/i.test(navigator.userAge
export const IS_TOUCH_ENV = window.matchMedia('(pointer: coarse)').matches; export const IS_TOUCH_ENV = window.matchMedia('(pointer: coarse)').matches;
// Keep in mind the landscape orientation // Keep in mind the landscape orientation
export const IS_MOBILE_SCREEN = window.innerWidth <= MOBILE_SCREEN_MAX_WIDTH || ( export const IS_SINGLE_COLUMN_LAYOUT = window.innerWidth <= MOBILE_SCREEN_MAX_WIDTH || (
window.innerWidth <= MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH && window.innerHeight <= MOBILE_SCREEN_LANDSCAPE_MAX_HEIGHT window.innerWidth <= MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH && window.innerHeight <= MOBILE_SCREEN_LANDSCAPE_MAX_HEIGHT
); );
export const IS_VOICE_RECORDING_SUPPORTED = (navigator.mediaDevices && 'getUserMedia' in navigator.mediaDevices && ( export const IS_VOICE_RECORDING_SUPPORTED = (navigator.mediaDevices && 'getUserMedia' in navigator.mediaDevices && (

View File

@ -4,21 +4,21 @@ import {
MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH, MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH,
MOBILE_SCREEN_MAX_WIDTH, MOBILE_SCREEN_MAX_WIDTH,
} from '../config'; } from '../config';
import { IS_IOS, IS_MOBILE_SCREEN } from './environment'; import { IS_IOS, IS_SINGLE_COLUMN_LAYOUT } from './environment';
type IDimensions = { type IDimensions = {
width: number; width: number;
height: number; height: number;
}; };
const IS_LANDSCAPE = IS_MOBILE_SCREEN && isLandscape(); const IS_LANDSCAPE = IS_SINGLE_COLUMN_LAYOUT && isLandscape();
let windowSize = updateSizes(); let windowSize = updateSizes();
const handleResize = throttle(() => { const handleResize = throttle(() => {
windowSize = updateSizes(); windowSize = updateSizes();
if ((isMobileScreen() !== IS_MOBILE_SCREEN) || (IS_MOBILE_SCREEN && IS_LANDSCAPE !== isLandscape())) { if ((isMobileScreen() !== IS_SINGLE_COLUMN_LAYOUT) || (IS_SINGLE_COLUMN_LAYOUT && IS_LANDSCAPE !== isLandscape())) {
window.location.reload(); window.location.reload();
} }
}, 250, true); }, 250, true);