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');
|
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;
|
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 {
|
.root {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|||||||
@ -838,7 +838,12 @@ function Story({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{isLoadedStory && fullMediaData && (
|
{isLoadedStory && fullMediaData && (
|
||||||
<MediaAreaOverlay story={story} isActive />
|
<MediaAreaOverlay
|
||||||
|
key={`area-overlay-${storyId}-${peerId}`}
|
||||||
|
story={story}
|
||||||
|
isActive
|
||||||
|
isStoryPlaying={isDropdownMenuOpen}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<div className={styles.content}>
|
<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 {
|
.reaction {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@ -141,26 +134,27 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weatherInfo {
|
.weather {
|
||||||
width: 100%;
|
display: grid;
|
||||||
height: 100%;
|
place-items: center;
|
||||||
position: absolute;
|
}
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
.weatherInner {
|
||||||
transform: translate(-50%, -50%);
|
width: auto !important;
|
||||||
transition: transform 200ms ease-out;
|
height: auto !important;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.3125rem;
|
gap: 0.2em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
padding: 0 0.2em;
|
||||||
|
background-color: var(--custom-background-color);
|
||||||
|
border-radius: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.temperature {
|
.temperature {
|
||||||
|
font-family: var(--font-family-condensed);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin: 0;
|
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 { getActions } from '../../../global';
|
||||||
|
|
||||||
import type { ApiMediaArea, ApiStory } from '../../../api/types';
|
import type { ApiMediaArea, ApiStory } from '../../../api/types';
|
||||||
@ -18,13 +20,15 @@ import styles from './MediaArea.module.scss';
|
|||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
story: ApiStory;
|
story: ApiStory;
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
|
isStoryPlaying?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const STORY_ASPECT_RATIO = 9 / 16;
|
const STORY_ASPECT_RATIO = 9 / 16;
|
||||||
|
const PERCENTAGE_BASE = 100;
|
||||||
|
|
||||||
const MediaAreaOverlay = ({
|
const MediaAreaOverlay = ({
|
||||||
story, isActive, className,
|
story, isActive, className, isStoryPlaying,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
const {
|
const {
|
||||||
openMapModal, focusMessage, closeStoryViewer, openUrl,
|
openMapModal, focusMessage, closeStoryViewer, openUrl,
|
||||||
@ -32,12 +36,14 @@ const MediaAreaOverlay = ({
|
|||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const [mediaWidth, setMediaWidth] = useState(0);
|
||||||
|
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ref.current || !isActive) return;
|
if (!ref.current) return;
|
||||||
const element = ref.current;
|
const element = ref.current;
|
||||||
|
setMediaWidth(element!.clientWidth!);
|
||||||
|
|
||||||
if (windowSize.width > MOBILE_SCREEN_MAX_WIDTH) {
|
if (windowSize.width > MOBILE_SCREEN_MAX_WIDTH) {
|
||||||
requestMutation(() => {
|
requestMutation(() => {
|
||||||
@ -124,8 +130,8 @@ const MediaAreaOverlay = ({
|
|||||||
key={`${mediaArea.type}-${i}`}
|
key={`${mediaArea.type}-${i}`}
|
||||||
mediaArea={mediaArea}
|
mediaArea={mediaArea}
|
||||||
className={styles.mediaArea}
|
className={styles.mediaArea}
|
||||||
style={prepareStyle(mediaArea)}
|
style={prepareStyle(mediaArea, mediaWidth)}
|
||||||
isPreview={isActive}
|
isPreview={!isActive || isStoryPlaying}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -137,18 +143,26 @@ const MediaAreaOverlay = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function prepareStyle(mediaArea: ApiMediaArea) {
|
function prepareStyle(mediaArea: ApiMediaArea, mediaWidth?: number) {
|
||||||
const {
|
const {
|
||||||
x, y, width, height, rotation, radius,
|
x, y, width, height, rotation, radius,
|
||||||
} = mediaArea.coordinates;
|
} = 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(
|
return buildStyle(
|
||||||
`left: ${x}%`,
|
`left: ${x}%`,
|
||||||
`top: ${y}%`,
|
`top: ${y}%`,
|
||||||
`width: ${width}%`,
|
`width: ${width}%`,
|
||||||
`height: ${height}%`,
|
`height: ${height}%`,
|
||||||
`transform: rotate(${rotation}deg) translate(-50%, -50%)`,
|
`transform: rotate(${rotation}deg) translate(-50%, -50%)`,
|
||||||
Boolean(radius) && `border-radius: ${radius}%`,
|
pixelRadius && `border-radius: ${pixelRadius}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
import React, {
|
import React, {
|
||||||
type FC, memo, useRef, useState,
|
type FC, memo,
|
||||||
|
useLayoutEffect,
|
||||||
|
useRef, useState,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
|
import { setExtraStyles } from '../../../lib/teact/teact-dom';
|
||||||
import { withGlobal } from '../../../global';
|
import { withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiMediaAreaWeather, ApiSticker } from '../../../api/types';
|
import type { ApiMediaAreaWeather, ApiSticker } from '../../../api/types';
|
||||||
|
|
||||||
|
import { requestForcedReflow, requestMutation } from '../../../lib/fasterdom/fasterdom';
|
||||||
import { selectRestrictedEmoji } from '../../../global/selectors';
|
import { selectRestrictedEmoji } from '../../../global/selectors';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import buildStyle from '../../../util/buildStyle';
|
import buildStyle from '../../../util/buildStyle';
|
||||||
import { convertToRGBA, getTextColor } from '../../../util/colors';
|
import { convertToRGBA, getTextColor } from '../../../util/colors';
|
||||||
import { formatTemperature } from '../../../util/formatTemperature';
|
import { formatTemperature } from '../../../util/formatTemperature';
|
||||||
import { REM } from '../../common/helpers/mediaDimensions';
|
|
||||||
|
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useResizeObserver from '../../../hooks/useResizeObserver';
|
import useResizeObserver from '../../../hooks/useResizeObserver';
|
||||||
@ -42,48 +45,62 @@ const MediaAreaWeather: FC<OwnProps & StateProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [customEmojiSize, setCustomEmojiSize] = useState(1.5 * REM);
|
const [customEmojiSize, setCustomEmojiSize] = useState(0);
|
||||||
const [customTemperatureSize, setCustomTemperatureSize] = useState(0);
|
|
||||||
|
|
||||||
const { temperatureC, color } = mediaArea;
|
const { temperatureC, color } = mediaArea;
|
||||||
|
|
||||||
const backgroundColor = convertToRGBA(color);
|
const backgroundColor = convertToRGBA(color);
|
||||||
const textColor = getTextColor(color);
|
const textColor = getTextColor(color);
|
||||||
|
|
||||||
const updateCustomSize = useLastCallback(() => {
|
const updateCustomSize = useLastCallback((isImmediate?: boolean) => {
|
||||||
if (!ref.current) return;
|
if (!ref.current) return undefined;
|
||||||
const height = ref.current.clientHeight;
|
const el = ref.current;
|
||||||
setCustomEmojiSize(Math.round(height * EMOJI_SIZE_MULTIPLIER));
|
|
||||||
setCustomTemperatureSize(height / TEMPERATURE_SIZE);
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={buildClassName(className, styles.withBackground, isPreview && styles.border)}
|
className={buildClassName(styles.weather, className)}
|
||||||
style={buildStyle(
|
style={buildStyle(
|
||||||
style,
|
style,
|
||||||
`--custom-emoji-size: ${customEmojiSize}px`,
|
|
||||||
`--custom-background-color: ${backgroundColor}`,
|
`--custom-background-color: ${backgroundColor}`,
|
||||||
|
`color: ${textColor}`,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className={styles.weatherInfo}>
|
<div className={styles.weatherInner}>
|
||||||
{restrictedEmoji && (
|
{restrictedEmoji && (
|
||||||
<CustomEmoji
|
<CustomEmoji
|
||||||
key={restrictedEmoji.id}
|
key={restrictedEmoji.id}
|
||||||
documentId={restrictedEmoji.id}
|
documentId={restrictedEmoji.id}
|
||||||
size={customEmojiSize}
|
size={customEmojiSize}
|
||||||
noPlay={!isPreview}
|
noPlay={isPreview}
|
||||||
withTranslucentThumb
|
withTranslucentThumb
|
||||||
forceAlways
|
forceAlways
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<p
|
<p className={styles.temperature}>
|
||||||
className={styles.temperature}
|
|
||||||
style={buildStyle(`font-size: ${customTemperatureSize}rem`, `color: ${textColor}`)}
|
|
||||||
>
|
|
||||||
{formatTemperature(temperatureC)}
|
{formatTemperature(temperatureC)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -30,10 +30,11 @@ body {
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
--font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI", Oxygen, Ubuntu,
|
--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",
|
--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-rounded: -ui-rounded, "Roboto Round";
|
||||||
|
--font-family-condensed: -ui-rounded, "Roboto Condensed";
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
height: calc(var(--vh, 1vh) * 100);
|
height: calc(var(--vh, 1vh) * 100);
|
||||||
@ -61,18 +62,18 @@ html.theme-dark {
|
|||||||
body.is-ios,
|
body.is-ios,
|
||||||
body.is-macos {
|
body.is-macos {
|
||||||
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Roboto", "Apple Color Emoji", "Helvetica Neue",
|
--font-family: system-ui, -apple-system, BlinkMacSystemFont, "Roboto", "Apple Color Emoji", "Helvetica Neue",
|
||||||
sans-serif;
|
sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[lang="fa"],
|
html[lang="fa"],
|
||||||
html[lang="fa"] body {
|
html[lang="fa"] body {
|
||||||
--font-family: "Vazirmatn", "Roboto", -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI", Oxygen,
|
--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-ios,
|
||||||
&.is-macos {
|
&.is-macos {
|
||||||
--font-family: "Vazirmatn", -apple-system, BlinkMacSystemFont, "Roboto", "Apple Color Emoji", "Segoe UI", Oxygen,
|
--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) => {
|
export const formatTemperature = (temperatureC: number) => {
|
||||||
const isFahrenheit = Boolean(navigator.language === 'en-US');
|
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