Weather Widget: Adjust styles for weather widget (#5059)
Co-authored-by: zubiden <19638254+zubiden@users.noreply.github.com>
This commit is contained in:
parent
c967e86551
commit
8a7095f640
BIN
src/assets/fonts/Roboto-Condensed-Regular.woff2
Normal file
BIN
src/assets/fonts/Roboto-Condensed-Regular.woff2
Normal file
Binary file not shown.
@ -151,3 +151,10 @@
|
||||
src: url('Roboto-Round-Regular.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto Condensed';
|
||||
src: url('Roboto-Condensed-Regular.woff2') format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
.root {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
|
||||
@ -838,7 +838,12 @@ function Story({
|
||||
</>
|
||||
)}
|
||||
{isLoadedStory && fullMediaData && (
|
||||
<MediaAreaOverlay story={story} isActive />
|
||||
<MediaAreaOverlay
|
||||
key={`area-overlay-${storyId}-${peerId}`}
|
||||
story={story}
|
||||
isActive
|
||||
isStoryPlaying={isDropdownMenuOpen}
|
||||
/>
|
||||
)}
|
||||
{!isMobile && (
|
||||
<div className={styles.content}>
|
||||
|
||||
@ -114,13 +114,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.withBackground {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--custom-background-color);
|
||||
filter: drop-shadow(0 0.125rem 0.25rem var(--color-default-shadow));
|
||||
}
|
||||
|
||||
.reaction {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@ -141,26 +134,27 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.weatherInfo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: transform 200ms ease-out;
|
||||
.weather {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.weatherInner {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.3125rem;
|
||||
gap: 0.2em;
|
||||
white-space: nowrap;
|
||||
padding: 0 0.2em;
|
||||
background-color: var(--custom-background-color);
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
.temperature {
|
||||
font-family: var(--font-family-condensed);
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-radius: 0.3125rem !important;
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import React, { memo, useEffect, useRef } from '../../../lib/teact/teact';
|
||||
import React, {
|
||||
memo, useEffect, useRef, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { ApiMediaArea, ApiStory } from '../../../api/types';
|
||||
@ -18,13 +20,15 @@ import styles from './MediaArea.module.scss';
|
||||
type OwnProps = {
|
||||
story: ApiStory;
|
||||
isActive?: boolean;
|
||||
isStoryPlaying?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const STORY_ASPECT_RATIO = 9 / 16;
|
||||
const PERCENTAGE_BASE = 100;
|
||||
|
||||
const MediaAreaOverlay = ({
|
||||
story, isActive, className,
|
||||
story, isActive, className, isStoryPlaying,
|
||||
}: OwnProps) => {
|
||||
const {
|
||||
openMapModal, focusMessage, closeStoryViewer, openUrl,
|
||||
@ -32,12 +36,14 @@ const MediaAreaOverlay = ({
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [mediaWidth, setMediaWidth] = useState(0);
|
||||
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
useEffect(() => {
|
||||
if (!ref.current || !isActive) return;
|
||||
if (!ref.current) return;
|
||||
const element = ref.current;
|
||||
setMediaWidth(element!.clientWidth!);
|
||||
|
||||
if (windowSize.width > MOBILE_SCREEN_MAX_WIDTH) {
|
||||
requestMutation(() => {
|
||||
@ -124,8 +130,8 @@ const MediaAreaOverlay = ({
|
||||
key={`${mediaArea.type}-${i}`}
|
||||
mediaArea={mediaArea}
|
||||
className={styles.mediaArea}
|
||||
style={prepareStyle(mediaArea)}
|
||||
isPreview={isActive}
|
||||
style={prepareStyle(mediaArea, mediaWidth)}
|
||||
isPreview={!isActive || isStoryPlaying}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -137,18 +143,26 @@ const MediaAreaOverlay = ({
|
||||
);
|
||||
};
|
||||
|
||||
function prepareStyle(mediaArea: ApiMediaArea) {
|
||||
function prepareStyle(mediaArea: ApiMediaArea, mediaWidth?: number) {
|
||||
const {
|
||||
x, y, width, height, rotation, radius,
|
||||
} = mediaArea.coordinates;
|
||||
|
||||
let pixelRadius = '';
|
||||
|
||||
if (mediaWidth && radius && mediaWidth > 0) {
|
||||
const pixelWidth = (mediaWidth * (width / PERCENTAGE_BASE));
|
||||
const pixelHeight = (mediaWidth * (height / PERCENTAGE_BASE));
|
||||
pixelRadius = `${Math.min(pixelWidth, pixelHeight) * (radius / PERCENTAGE_BASE)}px`;
|
||||
}
|
||||
|
||||
return buildStyle(
|
||||
`left: ${x}%`,
|
||||
`top: ${y}%`,
|
||||
`width: ${width}%`,
|
||||
`height: ${height}%`,
|
||||
`transform: rotate(${rotation}deg) translate(-50%, -50%)`,
|
||||
Boolean(radius) && `border-radius: ${radius}%`,
|
||||
pixelRadius && `border-radius: ${pixelRadius}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
import React, {
|
||||
type FC, memo, useRef, useState,
|
||||
type FC, memo,
|
||||
useLayoutEffect,
|
||||
useRef, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { setExtraStyles } from '../../../lib/teact/teact-dom';
|
||||
import { withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiMediaAreaWeather, ApiSticker } from '../../../api/types';
|
||||
|
||||
import { requestForcedReflow, requestMutation } from '../../../lib/fasterdom/fasterdom';
|
||||
import { selectRestrictedEmoji } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import buildStyle from '../../../util/buildStyle';
|
||||
import { convertToRGBA, getTextColor } from '../../../util/colors';
|
||||
import { formatTemperature } from '../../../util/formatTemperature';
|
||||
import { REM } from '../../common/helpers/mediaDimensions';
|
||||
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useResizeObserver from '../../../hooks/useResizeObserver';
|
||||
@ -42,48 +45,62 @@ const MediaAreaWeather: FC<OwnProps & StateProps> = ({
|
||||
}) => {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [customEmojiSize, setCustomEmojiSize] = useState(1.5 * REM);
|
||||
const [customTemperatureSize, setCustomTemperatureSize] = useState(0);
|
||||
const [customEmojiSize, setCustomEmojiSize] = useState(0);
|
||||
|
||||
const { temperatureC, color } = mediaArea;
|
||||
|
||||
const backgroundColor = convertToRGBA(color);
|
||||
const textColor = getTextColor(color);
|
||||
|
||||
const updateCustomSize = useLastCallback(() => {
|
||||
if (!ref.current) return;
|
||||
const height = ref.current.clientHeight;
|
||||
setCustomEmojiSize(Math.round(height * EMOJI_SIZE_MULTIPLIER));
|
||||
setCustomTemperatureSize(height / TEMPERATURE_SIZE);
|
||||
const updateCustomSize = useLastCallback((isImmediate?: boolean) => {
|
||||
if (!ref.current) return undefined;
|
||||
const el = ref.current;
|
||||
|
||||
const height = el.clientHeight;
|
||||
const customEmojiHeight = Math.round(height * EMOJI_SIZE_MULTIPLIER);
|
||||
setCustomEmojiSize(customEmojiHeight);
|
||||
const applyFn = () => {
|
||||
setExtraStyles(el, {
|
||||
'--custom-emoji-size': `${customEmojiHeight}px`,
|
||||
'font-size': `${height / TEMPERATURE_SIZE}rem`,
|
||||
});
|
||||
};
|
||||
|
||||
if (isImmediate) return applyFn;
|
||||
|
||||
requestMutation(applyFn);
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
useResizeObserver(ref, updateCustomSize);
|
||||
useLayoutEffect(() => {
|
||||
requestForcedReflow(() => updateCustomSize(true));
|
||||
}, []);
|
||||
|
||||
useResizeObserver(ref, () => updateCustomSize());
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={buildClassName(className, styles.withBackground, isPreview && styles.border)}
|
||||
className={buildClassName(styles.weather, className)}
|
||||
style={buildStyle(
|
||||
style,
|
||||
`--custom-emoji-size: ${customEmojiSize}px`,
|
||||
`--custom-background-color: ${backgroundColor}`,
|
||||
`color: ${textColor}`,
|
||||
)}
|
||||
>
|
||||
<div className={styles.weatherInfo}>
|
||||
<div className={styles.weatherInner}>
|
||||
{restrictedEmoji && (
|
||||
<CustomEmoji
|
||||
key={restrictedEmoji.id}
|
||||
documentId={restrictedEmoji.id}
|
||||
size={customEmojiSize}
|
||||
noPlay={!isPreview}
|
||||
noPlay={isPreview}
|
||||
withTranslucentThumb
|
||||
forceAlways
|
||||
/>
|
||||
)}
|
||||
<p
|
||||
className={styles.temperature}
|
||||
style={buildStyle(`font-size: ${customTemperatureSize}rem`, `color: ${textColor}`)}
|
||||
>
|
||||
<p className={styles.temperature}>
|
||||
{formatTemperature(temperatureC)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -30,10 +30,11 @@ body {
|
||||
user-select: none;
|
||||
|
||||
--font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI", Oxygen, Ubuntu,
|
||||
Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
--font-family-monospace: "Cascadia Mono", "Roboto Mono", "Droid Sans Mono", 'SF Mono', "Menlo", "Ubuntu Mono",
|
||||
"Consolas", monospace;
|
||||
"Consolas", monospace;
|
||||
--font-family-rounded: -ui-rounded, "Roboto Round";
|
||||
--font-family-condensed: -ui-rounded, "Roboto Condensed";
|
||||
|
||||
@media (max-width: 600px) {
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
@ -61,18 +62,18 @@ html.theme-dark {
|
||||
body.is-ios,
|
||||
body.is-macos {
|
||||
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Roboto", "Apple Color Emoji", "Helvetica Neue",
|
||||
sans-serif;
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
html[lang="fa"],
|
||||
html[lang="fa"] body {
|
||||
--font-family: "Vazirmatn", "Roboto", -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI", Oxygen,
|
||||
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
|
||||
&.is-ios,
|
||||
&.is-macos {
|
||||
--font-family: "Vazirmatn", -apple-system, BlinkMacSystemFont, "Roboto", "Apple Color Emoji", "Segoe UI", Oxygen,
|
||||
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export const formatTemperature = (temperatureC: number) => {
|
||||
const isFahrenheit = Boolean(navigator.language === 'en-US');
|
||||
return isFahrenheit ? `${Math.round((temperatureC * 9) / 5 + 32)} °F` : `${Math.round(temperatureC)} °C`;
|
||||
return isFahrenheit ? `${Math.round((temperatureC * 9) / 5 + 32)}°F` : `${Math.round(temperatureC)}°C`;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user