87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import { useEffect } from '../lib/teact/teact';
|
|
|
|
import {
|
|
MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN,
|
|
MOBILE_SCREEN_LANDSCAPE_MAX_HEIGHT,
|
|
MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH,
|
|
MOBILE_SCREEN_MAX_WIDTH,
|
|
} from '../config';
|
|
import { IS_IOS } from '../util/browser/windowEnvironment';
|
|
import { createCallbackManager } from '../util/callbacks';
|
|
import { updateSizes } from '../util/windowSize';
|
|
import useForceUpdate from './useForceUpdate';
|
|
|
|
type MediaQueryCacheKey = 'mobile' | 'tablet' | 'landscape' | 'touch';
|
|
|
|
const mediaQueryCache = new Map<MediaQueryCacheKey, MediaQueryList>();
|
|
const callbacks = createCallbackManager();
|
|
|
|
let isMobile: boolean;
|
|
let isTablet: boolean;
|
|
let isLandscape: boolean;
|
|
let isTouchScreen: boolean;
|
|
|
|
export function getIsMobile() {
|
|
return isMobile;
|
|
}
|
|
|
|
export function getIsTablet() {
|
|
return isTablet;
|
|
}
|
|
|
|
export function getIsWebAppsFullscreenSupported() {
|
|
return !getIsMobile();
|
|
}
|
|
|
|
function handleMediaQueryChange() {
|
|
isMobile = mediaQueryCache.get('mobile')?.matches || false;
|
|
isTablet = !isMobile && (mediaQueryCache.get('tablet')?.matches || false);
|
|
isLandscape = mediaQueryCache.get('landscape')?.matches || false;
|
|
isTouchScreen = mediaQueryCache.get('touch')?.matches || false;
|
|
updateSizes();
|
|
callbacks.runCallbacks();
|
|
}
|
|
|
|
function initMediaQueryCache() {
|
|
const mobileQuery = window.matchMedia(`(max-width: ${MOBILE_SCREEN_MAX_WIDTH}px), \
|
|
(max-width: ${MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH}px and max-height: ${MOBILE_SCREEN_LANDSCAPE_MAX_HEIGHT}px)`);
|
|
mediaQueryCache.set('mobile', mobileQuery);
|
|
mobileQuery.addEventListener('change', handleMediaQueryChange);
|
|
|
|
const tabletQuery = window.matchMedia(`(max-width: ${MIN_SCREEN_WIDTH_FOR_STATIC_LEFT_COLUMN}px)`);
|
|
mediaQueryCache.set('tablet', tabletQuery);
|
|
tabletQuery.addEventListener('change', handleMediaQueryChange);
|
|
|
|
const landscapeQuery = window.matchMedia(
|
|
IS_IOS
|
|
? '(orientation: landscape)'
|
|
// Source: https://web.archive.org/web/20160509220835/http://blog.abouthalf.com/development/orientation-media-query-challenges-in-android-browsers/
|
|
// Feature is marked as deprecated now, but it is still supported
|
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/@media/device-aspect-ratio#browser_compatibility
|
|
: 'screen and (min-device-aspect-ratio: 1/1) and (orientation: landscape)',
|
|
);
|
|
mediaQueryCache.set('landscape', landscapeQuery);
|
|
landscapeQuery.addEventListener('change', handleMediaQueryChange);
|
|
|
|
const isTouchScreenQuery = window.matchMedia('(pointer: coarse)');
|
|
mediaQueryCache.set('touch', isTouchScreenQuery);
|
|
isTouchScreenQuery.addEventListener('change', handleMediaQueryChange);
|
|
}
|
|
|
|
initMediaQueryCache();
|
|
handleMediaQueryChange();
|
|
|
|
export default function useAppLayout() {
|
|
const forceUpdate = useForceUpdate();
|
|
|
|
useEffect(() => callbacks.addCallback(forceUpdate), [forceUpdate]);
|
|
|
|
return {
|
|
isMobile,
|
|
isTablet,
|
|
isLandscape,
|
|
isDesktop: !isMobile && !isTablet,
|
|
isTouchScreen,
|
|
};
|
|
}
|