Weather Widget: Adjust styles for weather widget (#5059)

Co-authored-by: zubiden <19638254+zubiden@users.noreply.github.com>
This commit is contained in:
Alexander Zinchuk 2024-10-26 13:01:47 +04:00
parent c967e86551
commit 8a7095f640
9 changed files with 91 additions and 52 deletions

Binary file not shown.

View File

@ -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;
}

View File

@ -1,5 +1,6 @@
.root {
position: relative;
overflow: hidden;
}
.wrapper {

View File

@ -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}>

View File

@ -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;
}

View File

@ -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}`,
);
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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`;
};