Redesign: Follow Up (#6966)

This commit is contained in:
Alexander Zinchuk 2026-06-01 01:16:15 +02:00
parent 8edd3fe4ba
commit d82240b06c
18 changed files with 69 additions and 66 deletions

View File

@ -59,6 +59,7 @@ type BaseOwnProps = {
noVerified?: boolean; noVerified?: boolean;
emojiStatusSize?: number; emojiStatusSize?: number;
noStatusOrTyping?: boolean; noStatusOrTyping?: boolean;
noUserStatus?: boolean;
noRtl?: boolean; noRtl?: boolean;
chatMemberOriginId?: string; chatMemberOriginId?: string;
chatMember?: ApiChatMember; chatMember?: ApiChatMember;
@ -109,6 +110,7 @@ const PrivateChatInfo = ({
withUpdatingStatus, withUpdatingStatus,
emojiStatusSize, emojiStatusSize,
noStatusOrTyping, noStatusOrTyping,
noUserStatus,
noEmojiStatus, noEmojiStatus,
noFake, noFake,
noVerified, noVerified,
@ -231,10 +233,10 @@ const PrivateChatInfo = ({
return undefined; return undefined;
} }
const translatedStatus = getUserStatus(oldLang, user, userStatus); const translatedStatus = noUserStatus ? undefined : getUserStatus(oldLang, user, userStatus);
const mainUserNameClassName = buildClassName('handle', translatedStatus && 'withStatus'); const mainUserNameClassName = buildClassName('handle', translatedStatus && 'withStatus');
return ( return (
<span className={buildClassName('status', isUserOnline(user, userStatus, true) && 'online')}> <span className={buildClassName('status', !noUserStatus && isUserOnline(user, userStatus, true) && 'online')}>
{mainUsername && <span className={mainUserNameClassName}>{mainUsername}</span>} {mainUsername && <span className={mainUserNameClassName}>{mainUsername}</span>}
{translatedStatus && <span className="user-status" dir="auto">{translatedStatus}</span>} {translatedStatus && <span className="user-status" dir="auto">{translatedStatus}</span>}
</span> </span>

View File

@ -54,6 +54,7 @@ const Switch = ({
return ( return (
<span <span
className={buildClassName( className={buildClassName(
'Switch',
styles.root, styles.root,
isDisabled && styles.disabled, isDisabled && styles.disabled,
locked && styles.locked, locked && styles.locked,

View File

@ -3,6 +3,21 @@
#Settings { #Settings {
height: 100%; height: 100%;
.multiline-item .title-with-date {
display: flex;
justify-content: space-between;
.date {
flex-shrink: 0;
margin-inline-start: 1rem;
font-size: 0.75rem;
font-weight: normal;
color: var(--color-text-secondary);
}
}
.chat-list { .chat-list {
padding-bottom: 0; padding-bottom: 0;
@ -228,13 +243,6 @@
.subtitle.tight { .subtitle.tight {
line-height: 1rem; line-height: 1rem;
} }
.date {
float: right;
margin-left: 1rem;
font-size: 0.75rem;
color: var(--color-text-secondary);
}
} }
&.destructive { &.destructive {
@ -247,14 +255,6 @@
} }
} }
&[dir="rtl"] {
.multiline-item .date {
float: left;
margin-right: 1rem;
margin-left: 0;
}
}
& + .settings-item-description { & + .settings-item-description {
margin-top: 0.5rem; margin-top: 0.5rem;
} }

View File

@ -9,8 +9,8 @@ import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Switcher from '../../ui/Switcher';
type StateProps = { type StateProps = {
disallowedGifts?: ApiDisallowedGiftsSettings; disallowedGifts?: ApiDisallowedGiftsSettings;
@ -97,40 +97,32 @@ const SettingsAcceptedGift = ({
<Island> <Island>
<ListItem onClick={handleLimitedEditionChange}> <ListItem onClick={handleLimitedEditionChange}>
<span>{lang('PrivacyGiftLimitedEdition')}</span> <span>{lang('PrivacyGiftLimitedEdition')}</span>
<Switcher <Switch
id="limited_edition" id="limited_edition"
label={disallowedGifts?.shouldDisallowLimitedStarGifts ? lang('PrivacyDisableLimitedEditionStarGifts')
: lang('PrivacyEnableLimitedEditionStarGifts')}
disabled={!isCurrentUserPremium} disabled={!isCurrentUserPremium}
checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowLimitedStarGifts} checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowLimitedStarGifts}
/> />
</ListItem> </ListItem>
<ListItem onClick={handleUnlimitedEditionChange}> <ListItem onClick={handleUnlimitedEditionChange}>
<span>{lang('PrivacyGiftUnlimited')}</span> <span>{lang('PrivacyGiftUnlimited')}</span>
<Switcher <Switch
id="unlimited" id="unlimited"
label={disallowedGifts?.shouldDisallowUnlimitedStarGifts ? lang('PrivacyDisableUnlimitedStarGifts')
: lang('PrivacyEnableUnlimitedStarGifts')}
disabled={!isCurrentUserPremium} disabled={!isCurrentUserPremium}
checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowUnlimitedStarGifts} checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowUnlimitedStarGifts}
/> />
</ListItem> </ListItem>
<ListItem onClick={handleUniqueChange}> <ListItem onClick={handleUniqueChange}>
<span>{lang('PrivacyGiftUnique')}</span> <span>{lang('PrivacyGiftUnique')}</span>
<Switcher <Switch
id="unique" id="unique"
label={disallowedGifts?.shouldDisallowUniqueStarGifts ? lang('PrivacyDisableUniqueStarGifts')
: lang('PrivacyEnableUniqueStarGifts')}
disabled={!isCurrentUserPremium} disabled={!isCurrentUserPremium}
checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowUniqueStarGifts} checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowUniqueStarGifts}
/> />
</ListItem> </ListItem>
<ListItem onClick={handlePremiumSubscriptionChange}> <ListItem onClick={handlePremiumSubscriptionChange}>
<span>{lang('PrivacyGiftPremiumSubscription')}</span> <span>{lang('PrivacyGiftPremiumSubscription')}</span>
<Switcher <Switch
id="premium_subscription" id="premium_subscription"
label={disallowedGifts?.shouldDisallowPremiumGifts ? lang('PrivacyDisablePremiumGifts')
: lang('PrivacyEnablePremiumGifts')}
disabled={!isCurrentUserPremium} disabled={!isCurrentUserPremium}
checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowPremiumGifts} checked={!isCurrentUserPremium ? true : !disallowedGifts?.shouldDisallowPremiumGifts}
/> />

View File

@ -11,10 +11,10 @@ import getSessionIcon from './helpers/getSessionIcon';
import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import Switch from '../../gili/primitives/Switch';
import Button from '../../ui/Button'; import Button from '../../ui/Button';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Modal from '../../ui/Modal'; import Modal from '../../ui/Modal';
import Switcher from '../../ui/Switcher';
import styles from './SettingsActiveSession.module.scss'; import styles from './SettingsActiveSession.module.scss';
@ -128,17 +128,15 @@ const SettingsActiveSession: FC<OwnProps & StateProps> = ({
<ListItem onClick={handleSecretChatsStateChange}> <ListItem onClick={handleSecretChatsStateChange}>
<span className={styles.actionName}>{lang('SessionPreviewAcceptSecret')}</span> <span className={styles.actionName}>{lang('SessionPreviewAcceptSecret')}</span>
<Switcher <Switch
id="accept_secrets" id="accept_secrets"
label="On"
checked={renderingSession.areSecretChatsEnabled} checked={renderingSession.areSecretChatsEnabled}
/> />
</ListItem> </ListItem>
<ListItem onClick={handleCallsStateChange}> <ListItem onClick={handleCallsStateChange}>
<span className={styles.actionName}>{lang('SessionPreviewAcceptCalls')}</span> <span className={styles.actionName}>{lang('SessionPreviewAcceptCalls')}</span>
<Switcher <Switch
id="accept_calls" id="accept_calls"
label="On"
checked={renderingSession.areCallsEnabled} checked={renderingSession.areCallsEnabled}
/> />
</ListItem> </ListItem>

View File

@ -239,8 +239,10 @@ const SettingsActiveSessions: FC<OwnProps & StateProps> = ({
onClick={() => { handleOpenSessionModal(session.hash); }} onClick={() => { handleOpenSessionModal(session.hash); }}
> >
<div className="multiline-item full-size" dir="auto"> <div className="multiline-item full-size" dir="auto">
<span className="date">{formatPastTimeShort(oldLang, session.dateActive * 1000)}</span> <span className="title title-with-date">
<span className="title">{session.deviceModel}</span> {session.deviceModel}
<span className="date">{formatPastTimeShort(oldLang, session.dateActive * 1000)}</span>
</span>
<span className="subtitle black tight"> <span className="subtitle black tight">
{session.appName} {session.appName}
{' '} {' '}

View File

@ -114,8 +114,10 @@ const SettingsActiveWebsites: FC<OwnProps & StateProps> = ({
> >
<Avatar className={styles.avatar} peer={bot} size="tiny" /> <Avatar className={styles.avatar} peer={bot} size="tiny" />
<div className="multiline-item full-size" dir="auto"> <div className="multiline-item full-size" dir="auto">
<span className="date">{formatPastTimeShort(lang, session.dateActive * 1000)}</span> <div className="title title-with-date">
{bot && <FullNameTitle className={styles.title} peer={bot} />} {bot && <FullNameTitle className={styles.title} peer={bot} />}
<span className="date">{formatPastTimeShort(lang, session.dateActive * 1000)}</span>
</div>
<span className={buildClassName('subtitle', 'black', 'tight', styles.platform)}> <span className={buildClassName('subtitle', 'black', 'tight', styles.platform)}>
{session.domain} {session.domain}
, ,

View File

@ -112,8 +112,10 @@ const SettingsPasskeys = ({
)} )}
> >
<div className="multiline-item full-size" dir="auto"> <div className="multiline-item full-size" dir="auto">
<span className="date">{formatDate(lang, secondsToDate(date))}</span> <span className="title title-with-date">
<span className="title">{name || lang('SettingsPasskeyFallbackTitle')}</span> {name || lang('SettingsPasskeyFallbackTitle')}
<span className="date">{formatDate(lang, secondsToDate(date))}</span>
</span>
{Boolean(lastUsageDate) && ( {Boolean(lastUsageDate) && (
<span className="subtitle"> <span className="subtitle">
{lang('SettingsPasskeyUsedAt', { {lang('SettingsPasskeyUsedAt', {

View File

@ -15,9 +15,9 @@ import useOldLang from '../../../hooks/useOldLang';
import Icon from '../../common/icons/Icon'; import Icon from '../../common/icons/Icon';
import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import RadioGroup from '../../ui/RadioGroup'; import RadioGroup from '../../ui/RadioGroup';
import Switcher from '../../ui/Switcher';
import PremiumStatusItem from './PremiumStatusItem'; import PremiumStatusItem from './PremiumStatusItem';
import PrivacyLockedOption from './PrivacyLockedOption'; import PrivacyLockedOption from './PrivacyLockedOption';
import SettingsAcceptedGift from './SettingsAcceptedGift'; import SettingsAcceptedGift from './SettingsAcceptedGift';
@ -100,11 +100,10 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
<Island> <Island>
<ListItem onClick={handleShowGiftIconInChats}> <ListItem onClick={handleShowGiftIconInChats}>
<span>{lang('PrivacyDisplayGiftsButton')}</span> <span>{lang('PrivacyDisplayGiftsButton')}</span>
<Switcher <Switch
id="gift" id="gift"
disabled={!isCurrentUserPremium} disabled={!isCurrentUserPremium}
label={shouldDisplayGiftsButton ? lang('HideGiftsButton') : lang('DisplayGiftsButton')} checked={Boolean(shouldDisplayGiftsButton)}
checked={shouldDisplayGiftsButton}
/> />
</ListItem> </ListItem>
</Island> </Island>

View File

@ -2,7 +2,7 @@
z-index: -1; z-index: -1;
flex-direction: column; flex-direction: column;
width: calc(100% - 4rem); width: calc(100% - 4rem);
max-width: 20rem; max-width: 25rem;
.ListItem.chat-item-clickable { .ListItem.chat-item-clickable {
margin: 0; margin: 0;

View File

@ -107,6 +107,7 @@ const MentionTooltip: FC<OwnProps> = ({
userId={id} userId={id}
avatarSize="small" avatarSize="small"
withUsername withUsername
noUserStatus
/> />
</ListItem> </ListItem>
))} ))}

View File

@ -164,6 +164,12 @@ const RightColumn: FC<OwnProps & StateProps> = ({
}); });
const [isAnimating, startAnimating, stopAnimating] = useFlag(); const [isAnimating, startAnimating, stopAnimating] = useFlag();
const wasOpenRef = useRef(false);
const shouldSkipOpenTransition = isOpen && !wasOpenRef.current;
useLayoutEffect(() => {
wasOpenRef.current = isOpen;
}, [isOpen]);
useLayoutEffect(() => { useLayoutEffect(() => {
const elements = containerRef.current?.querySelectorAll<HTMLElement>( const elements = containerRef.current?.querySelectorAll<HTMLElement>(
@ -437,7 +443,9 @@ const RightColumn: FC<OwnProps & StateProps> = ({
/> />
<Transition <Transition
ref={containerRef} ref={containerRef}
name={resolveTransitionName('layers', animationLevel, !isOpen || shouldSkipHistoryAnimations)} name={resolveTransitionName(
'layers', animationLevel, !isOpen || shouldSkipOpenTransition || shouldSkipHistoryAnimations,
)}
renderCount={MAIN_SCREENS_COUNT + MANAGEMENT_SCREENS_COUNT} renderCount={MAIN_SCREENS_COUNT + MANAGEMENT_SCREENS_COUNT}
activeKey={isManagement ? MAIN_SCREENS_COUNT + managementScreen : renderingContentKey} activeKey={isManagement ? MAIN_SCREENS_COUNT + managementScreen : renderingContentKey}
shouldCleanup shouldCleanup

View File

@ -22,12 +22,12 @@ import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Island from '../../gili/layout/Island'; import Island from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import AvatarEditable from '../../ui/AvatarEditable'; import AvatarEditable from '../../ui/AvatarEditable';
import ConfirmDialog from '../../ui/ConfirmDialog'; import ConfirmDialog from '../../ui/ConfirmDialog';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import InputText from '../../ui/InputText'; import InputText from '../../ui/InputText';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Switcher from '../../ui/Switcher';
import TextArea from '../../ui/TextArea'; import TextArea from '../../ui/TextArea';
import './Management.scss'; import './Management.scss';
@ -312,10 +312,9 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
onClick={handleAutoTranslationChange} onClick={handleAutoTranslationChange}
> >
<span>{lang('AutomaticTranslation')}</span> <span>{lang('AutomaticTranslation')}</span>
<Switcher <Switch
id="auto-translation" id="auto-translation"
label={lang('AutomaticTranslation')} checked={Boolean(hasAutoTranslation)}
checked={hasAutoTranslation}
/> />
</ListItem> </ListItem>
)} )}

View File

@ -29,13 +29,13 @@ import useMedia from '../../../hooks/useMedia';
import useOldLang from '../../../hooks/useOldLang'; import useOldLang from '../../../hooks/useOldLang';
import Island, { IslandDescription } from '../../gili/layout/Island'; import Island, { IslandDescription } from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import AvatarEditable from '../../ui/AvatarEditable'; import AvatarEditable from '../../ui/AvatarEditable';
import Checkbox from '../../ui/Checkbox'; import Checkbox from '../../ui/Checkbox';
import ConfirmDialog from '../../ui/ConfirmDialog'; import ConfirmDialog from '../../ui/ConfirmDialog';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import InputText from '../../ui/InputText'; import InputText from '../../ui/InputText';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Switcher from '../../ui/Switcher';
import TextArea from '../../ui/TextArea'; import TextArea from '../../ui/TextArea';
import './Management.scss'; import './Management.scss';
@ -425,11 +425,9 @@ const ManageGroup: FC<OwnProps & StateProps> = ({
<> <>
<ListItem icon="forums" ripple onClick={handleForumToggle}> <ListItem icon="forums" ripple onClick={handleForumToggle}>
<span>{lang('ChannelTopics')}</span> <span>{lang('ChannelTopics')}</span>
<Switcher <Switch
id="group-notifications" id="group-notifications"
label={lang('ChannelTopics')} checked={Boolean(isForumEnabled)}
checked={isForumEnabled}
inactive
/> />
</ListItem> </ListItem>
<IslandDescription>{lang('ForumToggleDescription')}</IslandDescription> <IslandDescription>{lang('ForumToggleDescription')}</IslandDescription>

View File

@ -28,12 +28,12 @@ import useOldLang from '../../../hooks/useOldLang';
import NothingFound from '../../common/NothingFound'; import NothingFound from '../../common/NothingFound';
import PrivateChatInfo from '../../common/PrivateChatInfo'; import PrivateChatInfo from '../../common/PrivateChatInfo';
import Island, { IslandDescription } from '../../gili/layout/Island'; import Island, { IslandDescription } from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import InfiniteScroll from '../../ui/InfiniteScroll'; import InfiniteScroll from '../../ui/InfiniteScroll';
import InputText from '../../ui/InputText'; import InputText from '../../ui/InputText';
import ListItem, { type MenuItemContextAction } from '../../ui/ListItem'; import ListItem, { type MenuItemContextAction } from '../../ui/ListItem';
import Loading from '../../ui/Loading'; import Loading from '../../ui/Loading';
import Switcher from '../../ui/Switcher';
import DeleteMemberModal from '../DeleteMemberModal'; import DeleteMemberModal from '../DeleteMemberModal';
type OwnProps = { type OwnProps = {
@ -216,7 +216,7 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
<Island> <Island>
<ListItem icon="group" ripple onClick={handleToggleParticipantsHidden}> <ListItem icon="group" ripple onClick={handleToggleParticipantsHidden}>
<span>{oldLang('ChannelHideMembers')}</span> <span>{oldLang('ChannelHideMembers')}</span>
<Switcher label={oldLang('ChannelHideMembers')} checked={areParticipantsHidden} /> <Switch checked={Boolean(areParticipantsHidden)} />
</ListItem> </ListItem>
</Island> </Island>
<IslandDescription> <IslandDescription>

View File

@ -28,10 +28,10 @@ import useManagePermissions from '../hooks/useManagePermissions';
import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice'; import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice';
import PrivateChatInfo from '../../common/PrivateChatInfo'; import PrivateChatInfo from '../../common/PrivateChatInfo';
import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island';
import Switch from '../../gili/primitives/Switch';
import PermissionCheckboxList from '../../main/PermissionCheckboxList'; import PermissionCheckboxList from '../../main/PermissionCheckboxList';
import FloatingActionButton from '../../ui/FloatingActionButton'; import FloatingActionButton from '../../ui/FloatingActionButton';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
import Switcher from '../../ui/Switcher';
type OwnProps = { type OwnProps = {
chatId: string; chatId: string;
@ -251,10 +251,9 @@ const ManageGroupPermissions: FC<OwnProps & StateProps> = ({
<Island> <Island>
<ListItem onClick={handleChargeStarsForMessages}> <ListItem onClick={handleChargeStarsForMessages}>
<span>{lang('GroupMessagesChargePrice')}</span> <span>{lang('GroupMessagesChargePrice')}</span>
<Switcher <Switch
id="charge_for_messages" id="charge_for_messages"
label={lang('GroupMessagesChargePrice')} checked={Boolean(isPriceForMessagesOpen)}
checked={isPriceForMessagesOpen}
/> />
</ListItem> </ListItem>
</Island> </Island>

View File

@ -67,7 +67,7 @@
} }
.invite-link { .invite-link {
padding: 0 1rem; padding: 0;
} }
.input-admin-title { .input-admin-title {
@ -205,7 +205,6 @@
.ManageInvite { .ManageInvite {
.link-name { .link-name {
margin-bottom: 1rem; margin-bottom: 1rem;
padding: 0 1rem;
} }
.expire-limit { .expire-limit {
@ -326,6 +325,6 @@
} }
.settings-edit { .settings-edit {
padding: 1.125rem !important; padding: 0.125rem;
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }

View File

@ -95,7 +95,8 @@
color: var(--color-text-secondary); color: var(--color-text-secondary);
} }
> .Switcher { > .Switcher,
> .Switch {
margin-inline-start: auto; margin-inline-start: auto;
} }