UserStatus: Design improvements (#4372)
This commit is contained in:
parent
18b1393fc3
commit
b3e21e293a
@ -69,7 +69,7 @@ const PrivacySettingsNoticeModal = ({ isOpen, isReadDate, user }: OwnProps & Sta
|
|||||||
closePrivacySettingsNoticeModal();
|
closePrivacySettingsNoticeModal();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
openPremiumModal();
|
openPremiumModal({ initialSection: 'last_seen' });
|
||||||
}, CLOSE_ANIMATION_DURATION);
|
}, CLOSE_ANIMATION_DURATION);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -176,9 +176,33 @@
|
|||||||
|
|
||||||
.status {
|
.status {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-status {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.get-status {
|
||||||
|
--blured-background-color: #c4c9cc42;
|
||||||
|
cursor: var(--custom-cursor, pointer);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin-inline-start: 0.375rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 0.1875rem 0.375rem;
|
||||||
|
pointer-events: all;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: 150ms filter ease-in;
|
||||||
|
background: var(--blured-background-color);
|
||||||
|
backdrop-filter: blur(100px);
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.topicContainer {
|
.topicContainer {
|
||||||
--custom-emoji-size: 7.5rem;
|
--custom-emoji-size: 7.5rem;
|
||||||
|
|
||||||
|
|||||||
@ -48,14 +48,4 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
cursor: var(--custom-cursor, pointer);
|
cursor: var(--custom-cursor, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
.get-status {
|
|
||||||
cursor: var(--custom-cursor, pointer);
|
|
||||||
margin-left: 0.375rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
padding: 0.125rem 0.375rem;
|
|
||||||
background: var(--color-background-menu-separator);
|
|
||||||
pointer-events: all;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -276,12 +276,12 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
|||||||
isUserOnline(user, userStatus) && 'online',
|
isUserOnline(user, userStatus) && 'online',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="user-status" dir="auto">
|
<span className={styles.userStatus} dir="auto">
|
||||||
{getUserStatus(lang, user, userStatus)}
|
{getUserStatus(lang, user, userStatus)}
|
||||||
</span>
|
</span>
|
||||||
{userStatus?.isReadDateRestrictedByMe && (
|
{userStatus?.isReadDateRestrictedByMe && (
|
||||||
<span className="get-status" onClick={handleOpenGetReadDateModal}>
|
<span className={styles.getStatus} onClick={handleOpenGetReadDateModal}>
|
||||||
{lang('StatusHiddenShow')}
|
<span>{lang('StatusHiddenShow')}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,16 +1,22 @@
|
|||||||
import React, { memo } from '../../../lib/teact/teact';
|
import React, { memo } from '../../../lib/teact/teact';
|
||||||
import { getActions } from '../../../global';
|
import { getActions } from '../../../global';
|
||||||
|
|
||||||
|
import type { ApiPremiumSection } from '../../../global/types';
|
||||||
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
import PremiumIcon from '../../common/PremiumIcon';
|
import PremiumIcon from '../../common/PremiumIcon';
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
|
|
||||||
function PremiumStatusItem() {
|
type OwnProps = {
|
||||||
|
premiumSection?: ApiPremiumSection;
|
||||||
|
};
|
||||||
|
|
||||||
|
function PremiumStatusItem({ premiumSection }: OwnProps) {
|
||||||
const { openPremiumModal } = getActions();
|
const { openPremiumModal } = getActions();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
const handleOpenPremiumModal = useLastCallback(() => openPremiumModal());
|
const handleOpenPremiumModal = useLastCallback(() => openPremiumModal({ initialSection: premiumSection }));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settings-item">
|
<div className="settings-item">
|
||||||
|
|||||||
@ -67,7 +67,7 @@ function PrivacyMessages({
|
|||||||
{lang('Privacy.Messages.SectionFooter')}
|
{lang('Privacy.Messages.SectionFooter')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{!isCurrentUserPremium && <PremiumStatusItem />}
|
{!isCurrentUserPremium && <PremiumStatusItem premiumSection="message_privacy" />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,24 +4,21 @@ import React, {
|
|||||||
import { getActions, getGlobal, withGlobal } from '../../../global';
|
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiChat } from '../../../api/types';
|
import type { ApiChat } from '../../../api/types';
|
||||||
import { ApiMediaFormat } from '../../../api/types';
|
|
||||||
|
|
||||||
import { getChatAvatarHash } from '../../../global/helpers';
|
|
||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectSimilarChannelIds,
|
selectSimilarChannelIds,
|
||||||
} from '../../../global/selectors';
|
} from '../../../global/selectors';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { getAverageColor, rgb2hex } from '../../../util/colors';
|
|
||||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||||
|
|
||||||
import useTimeout from '../../../hooks/schedulers/useTimeout';
|
import useTimeout from '../../../hooks/schedulers/useTimeout';
|
||||||
|
import useAverageColor from '../../../hooks/useAverageColor';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
|
||||||
|
|
||||||
import Avatar from '../../common/Avatar';
|
import Avatar from '../../common/Avatar';
|
||||||
import Icon from '../../common/Icon';
|
import Icon from '../../common/Icon';
|
||||||
@ -173,7 +170,7 @@ const SimilarChannels = ({
|
|||||||
|
|
||||||
function SimilarChannel({ channel }: { channel: ApiChat }) {
|
function SimilarChannel({ channel }: { channel: ApiChat }) {
|
||||||
const { openChat } = getActions();
|
const { openChat } = getActions();
|
||||||
const color = useAverageColor(channel);
|
const color = useAverageColor(channel, DEFAULT_BADGE_COLOR);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.item} onClick={() => openChat({ id: channel.id })}>
|
<div className={styles.item} onClick={() => openChat({ id: channel.id })}>
|
||||||
@ -233,24 +230,6 @@ function MoreChannels({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function useAverageColor(channel: ApiChat) {
|
|
||||||
const [color, setColor] = useState(DEFAULT_BADGE_COLOR);
|
|
||||||
const imgBlobUrl = useMedia(getChatAvatarHash(channel), false, ApiMediaFormat.BlobUrl);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (!imgBlobUrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const averageColor = await getAverageColor(imgBlobUrl);
|
|
||||||
setColor(`#${rgb2hex(averageColor)}`);
|
|
||||||
})();
|
|
||||||
}, [imgBlobUrl]);
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default memo(
|
export default memo(
|
||||||
withGlobal<OwnProps>((global, { chatId }): StateProps => {
|
withGlobal<OwnProps>((global, { chatId }): StateProps => {
|
||||||
const { similarChannelIds, shouldShowInChat, count } = selectSimilarChannelIds(global, chatId) || {};
|
const { similarChannelIds, shouldShowInChat, count } = selectSimilarChannelIds(global, chatId) || {};
|
||||||
|
|||||||
28
src/hooks/useAverageColor.ts
Normal file
28
src/hooks/useAverageColor.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { useEffect, useState } from '../lib/teact/teact';
|
||||||
|
|
||||||
|
import type { ApiChat } from '../api/types';
|
||||||
|
import { ApiMediaFormat } from '../api/types';
|
||||||
|
|
||||||
|
import { getChatAvatarHash } from '../global/helpers';
|
||||||
|
import { getAverageColor, rgb2hex } from '../util/colors';
|
||||||
|
import useMedia from './useMedia';
|
||||||
|
|
||||||
|
function useAverageColor(chat: ApiChat, fallbackColor = '#00000000') {
|
||||||
|
const [color, setColor] = useState(fallbackColor);
|
||||||
|
const imgBlobUrl = useMedia(getChatAvatarHash(chat), false, ApiMediaFormat.BlobUrl);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (!imgBlobUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const averageColor = await getAverageColor(imgBlobUrl);
|
||||||
|
setColor(`#${rgb2hex(averageColor)}`);
|
||||||
|
})();
|
||||||
|
}, [imgBlobUrl]);
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useAverageColor;
|
||||||
Loading…
x
Reference in New Issue
Block a user