From 60f3995e827cc3bd0b0cda7d12bf49453b1accc5 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Mon, 1 Jun 2026 01:15:35 +0200 Subject: [PATCH] Settings: Redesign (#6922) Co-authored-by: Alexander Zinchuk --- src/components/common/LinkField.tsx | 10 +- .../common/ManageUsernames.module.scss | 26 +- src/components/common/ManageUsernames.tsx | 17 +- src/components/common/pickers/PeerPicker.tsx | 132 +++++---- .../common/pickers/PickerStyles.module.scss | 20 ++ .../common/profile/BusinessHours.module.scss | 46 ++- .../common/profile/BusinessHours.tsx | 68 ++--- src/components/common/profile/ChatExtra.tsx | 16 +- .../common/profile/ProfileInfo.module.scss | 2 +- src/components/gili/layout/Island.module.scss | 5 + src/components/gili/layout/Island.tsx | 19 ++ src/components/left/LeftColumn.scss | 6 + src/components/left/LeftColumn.tsx | 8 +- .../left/settings/PremiumStatusItem.tsx | 26 +- .../left/settings/PrivacyMessages.tsx | 66 ++--- src/components/left/settings/Settings.scss | 125 ++++---- src/components/left/settings/Settings.tsx | 6 +- .../left/settings/SettingsAcceptedGift.tsx | 95 +++--- .../left/settings/SettingsActiveSessions.tsx | 116 ++++---- .../left/settings/SettingsActiveWebsites.tsx | 24 +- .../left/settings/SettingsCustomEmoji.tsx | 45 +-- .../left/settings/SettingsDataStorage.tsx | 65 ++--- .../SettingsDoNotTranslate.module.scss | 3 +- .../left/settings/SettingsDoNotTranslate.tsx | 17 +- .../left/settings/SettingsEditProfile.tsx | 95 +++--- .../left/settings/SettingsExperimental.tsx | 24 +- .../left/settings/SettingsGeneral.tsx | 47 ++- .../settings/SettingsGeneralBackground.scss | 18 +- .../settings/SettingsGeneralBackground.tsx | 5 +- .../SettingsGeneralBackgroundColor.scss | 16 +- .../SettingsGeneralBackgroundColor.tsx | 5 +- .../left/settings/SettingsHeader.tsx | 6 +- .../left/settings/SettingsLanguage.tsx | 85 +++--- .../left/settings/SettingsMain.module.scss | 22 ++ src/components/left/settings/SettingsMain.tsx | 274 +++++++++--------- .../left/settings/SettingsNotifications.tsx | 60 ++-- .../left/settings/SettingsPasskeys.tsx | 25 +- .../left/settings/SettingsPasswordForm.tsx | 33 ++- .../left/settings/SettingsPerformance.tsx | 25 +- .../left/settings/SettingsPrivacy.tsx | 118 ++++---- .../SettingsPrivacyBlockedUsers.module.scss | 15 + .../settings/SettingsPrivacyBlockedUsers.tsx | 43 +-- .../left/settings/SettingsPrivacyLastSeen.tsx | 38 +-- .../SettingsPrivacyPublicProfilePhoto.tsx | 67 +++-- .../settings/SettingsPrivacyVisibility.tsx | 109 +++---- ...SettingsPrivacyVisibilityExceptionList.tsx | 3 +- .../left/settings/SettingsQuickReaction.tsx | 22 +- .../left/settings/SettingsStickers.tsx | 61 ++-- .../settings/folders/SettingsFolders.scss | 15 +- .../folders/SettingsFoldersChatFilters.tsx | 3 +- .../settings/folders/SettingsFoldersEdit.tsx | 130 +++++---- .../settings/folders/SettingsFoldersMain.tsx | 123 ++++---- .../folders/SettingsShareChatlist.tsx | 22 +- .../SettingsPasscodeCongratulations.tsx | 4 +- .../passcode/SettingsPasscodeEnabled.tsx | 5 +- .../passcode/SettingsPasscodeStart.tsx | 4 +- .../twoFa/SettingsTwoFaCongratulations.tsx | 4 +- .../settings/twoFa/SettingsTwoFaEmailCode.tsx | 5 +- .../settings/twoFa/SettingsTwoFaEnabled.tsx | 5 +- .../twoFa/SettingsTwoFaSkippableForm.tsx | 7 +- .../settings/twoFa/SettingsTwoFaStart.tsx | 4 +- src/components/right/AddChatMembers.scss | 8 +- src/components/right/AddChatMembers.tsx | 1 + src/components/right/CreateTopic.tsx | 9 +- src/components/right/EditTopic.tsx | 9 +- src/components/right/ManageTopic.module.scss | 20 +- src/components/right/Profile.module.scss | 2 +- src/components/right/Profile.tsx | 1 - src/components/right/RightColumn.scss | 6 +- src/components/right/RightColumn.tsx | 82 +++--- src/components/right/management/ManageBot.tsx | 13 +- .../right/management/ManageChannel.tsx | 23 +- .../management/ManageChatAdministrators.tsx | 28 +- .../management/ManageChatPrivacyType.tsx | 113 ++++---- .../management/ManageChatRemovedUsers.tsx | 68 ++--- .../right/management/ManageDiscussion.tsx | 45 +-- .../right/management/ManageGroup.tsx | 27 +- .../management/ManageGroupAdminRights.tsx | 14 +- .../right/management/ManageGroupMembers.tsx | 67 +++-- .../management/ManageGroupPermissions.tsx | 57 ++-- .../management/ManageGroupUserPermissions.tsx | 15 +- .../ManageGroupUserPermissionsCreate.tsx | 26 +- .../right/management/ManageInvite.tsx | 79 ++--- .../right/management/ManageInviteInfo.tsx | 63 ++-- .../right/management/ManageInvites.tsx | 44 +-- .../right/management/ManageJoinRequests.tsx | 13 +- .../right/management/ManageReactions.tsx | 93 +++--- .../right/management/ManageUser.tsx | 79 ++--- .../right/management/Management.scss | 194 ++++++------- .../statistics/BoostStatistics.module.scss | 13 +- .../right/statistics/BoostStatistics.tsx | 224 +++++++------- .../right/statistics/MessageStatistics.tsx | 43 +-- .../MonetizationStatistics.module.scss | 19 +- .../statistics/MonetizationStatistics.tsx | 43 +-- .../right/statistics/Statistics.module.scss | 26 +- .../right/statistics/Statistics.tsx | 19 +- .../statistics/StatisticsOverview.module.scss | 8 +- src/components/ui/InputText.tsx | 3 + src/components/ui/Transition.scss | 24 +- src/hooks/useScrollNotch.ts | 11 +- src/lib/lovely-chart/styles/_buttons.scss | 2 +- src/lib/lovely-chart/styles/_common.scss | 20 +- src/lib/lovely-chart/styles/_minimap.scss | 22 +- src/lib/lovely-chart/styles/_tools.scss | 2 +- src/styles/_forms.scss | 6 +- 105 files changed, 2216 insertions(+), 1978 deletions(-) create mode 100644 src/components/left/settings/SettingsMain.module.scss create mode 100644 src/components/left/settings/SettingsPrivacyBlockedUsers.module.scss diff --git a/src/components/common/LinkField.tsx b/src/components/common/LinkField.tsx index 4139aca99..05891d793 100644 --- a/src/components/common/LinkField.tsx +++ b/src/components/common/LinkField.tsx @@ -22,6 +22,7 @@ type OwnProps = { isDisabled?: boolean; className?: string; withShare?: boolean; + noTitle?: boolean; onRevoke?: VoidFunction; }; @@ -31,6 +32,7 @@ const InviteLink: FC = ({ isDisabled, className, withShare, + noTitle, onRevoke, }) => { const lang = useLang(); @@ -76,9 +78,11 @@ const InviteLink: FC = ({ return (
-

- {oldLang(title || 'InviteLink.InviteLink')} -

+ {!noTitle && ( +

+ {oldLang(title || 'InviteLink.InviteLink')} +

+ )}
= ({ return ( <> -
-

- {oldLang('lng_usernames_subtitle')} -

+ + {oldLang('lng_usernames_subtitle')} + +
{usernames.map((usernameData, i) => { const isDragged = state.draggedIndex === i; @@ -201,10 +202,10 @@ const ManageUsernames: FC = ({ ); })}
-

- {oldLang('lng_usernames_description')} -

-
+ + + {oldLang('lng_usernames_description')} + = { withPeerTypes?: boolean; withPeerUsernames?: boolean; withDefaultPadding?: boolean; + withIslands?: boolean; onFilterChange?: (value: string) => void; onDisabledClick?: (id: string, isSelected: boolean) => void; onLoadMore?: () => void; @@ -125,6 +127,7 @@ const PeerPicker = ({ withPeerTypes, withPeerUsernames, withDefaultPadding, + withIslands, onFilterChange, onDisabledClick, onLoadMore, @@ -250,6 +253,19 @@ const PeerPicker = ({ onFilterChange?.(value); }); + function renderSearchInput() { + return ( + + ); + } + const [viewportIds, getMore] = useInfiniteScroll( onLoadMore, sortedItemIds, Boolean(filterValue), ); @@ -387,62 +403,78 @@ const PeerPicker = ({ ? sections.some((s) => s.ids.length > 0) : Boolean(viewportIds?.length); + const SearchWrapper = withIslands ? Island : 'div'; + const ListWrapper = withIslands ? Island : 'div'; + + function renderListWrapper(content: TeactNode) { + return withIslands + ? {content} + : content; + } + return (
{isSearchable && ( -
- {selectedCategories?.map((category) => ( - - ))} - {lockedSelectedIds?.map((id, i) => ( - - ))} - {unlockedSelectedIds.map((id, i) => ( - - ))} - -
+ <> + {(!withIslands || selectedIds.length > 0 || (selectedCategories && selectedCategories.length > 0)) && ( + + {selectedCategories?.map((category) => ( + + ))} + {lockedSelectedIds?.map((id, i) => ( + + ))} + {unlockedSelectedIds.map((id, i) => ( + + ))} + {!withIslands && renderSearchInput()} + + )} + {withIslands && ( + {renderSearchInput()} + )} + )} {hasContent ? ( - - {renderItems()} - + renderListWrapper( + + {renderItems()} + , + ) ) : !isLoading && viewportIds && !viewportIds.length ? (

{notFoundText || 'Sorry, nothing found.'}

) : ( diff --git a/src/components/common/pickers/PickerStyles.module.scss b/src/components/common/pickers/PickerStyles.module.scss index 4029bba8c..9acb6f4c7 100644 --- a/src/components/common/pickers/PickerStyles.module.scss +++ b/src/components/common/pickers/PickerStyles.module.scss @@ -32,6 +32,16 @@ } } +.islandHeader { + overflow-y: auto; + display: flex; + flex-flow: row wrap; + flex-shrink: 0; + + max-height: 16.5rem; + padding-bottom: 0; +} + .pickerCategoryTitle { margin-bottom: 0.5rem; padding-inline: 0.5rem; @@ -77,6 +87,16 @@ } } +.islandList { + overflow: hidden; + display: flex; + flex: 1 1 auto; + flex-direction: column; + + min-height: 0; + padding: 0; +} + .noResults { display: flex; align-items: center; diff --git a/src/components/common/profile/BusinessHours.module.scss b/src/components/common/profile/BusinessHours.module.scss index caa379988..cbe3490b4 100644 --- a/src/components/common/profile/BusinessHours.module.scss +++ b/src/components/common/profile/BusinessHours.module.scss @@ -17,12 +17,28 @@ margin-top: 1rem; } -.left, .bottom { +.left { display: flex; flex-direction: column; line-height: 1.4; } +.bottom { + overflow: hidden; + display: flex; + flex-direction: column; + + max-height: 25rem; + + /* stylelint-disable-next-line plugin/no-low-performance-animation-properties */ + transition: max-height 0.25s ease-in-out, opacity 0.25s ease-in-out; +} + +.collapsed { + max-height: 0; + opacity: 0; +} + .status { font-size: 0.875rem; color: var(--color-error); @@ -108,31 +124,3 @@ animation-name: none; } } - -@include mixins.on-active-vt('profileBusinessHoursExpand') { - &::view-transition-old(.expandArrow) { - animation-name: vt-expand-icon-spin; - } - - &::view-transition-new(.expandArrow) { - display: none; - } - - &::view-transition-old(.businessHours) { - display: none; - } -} - -@include mixins.on-active-vt('profileBusinessHoursCollapse') { - &::view-transition-old(.expandArrow) { - animation-name: vt-collapse-icon-spin; - } - - &::view-transition-new(.expandArrow) { - display: none; - } - - &::view-transition-new(.businessHours) { - display: none; - } -} diff --git a/src/components/common/profile/BusinessHours.tsx b/src/components/common/profile/BusinessHours.tsx index e453f3bd3..5b180925b 100644 --- a/src/components/common/profile/BusinessHours.tsx +++ b/src/components/common/profile/BusinessHours.tsx @@ -7,8 +7,6 @@ import type { ApiBusinessWorkHours } from '../../../api/types'; import { selectTimezones } from '../../../global/selectors'; import { VTT_PROFILE_BUSINESS_HOURS, - VTT_PROFILE_BUSINESS_HOURS_COLLAPSE, - VTT_PROFILE_BUSINESS_HOURS_EXPAND, } from '../../../util/animations/viewTransitionTypes'; import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; @@ -105,13 +103,9 @@ const BusinessHours = ({ const handleClick = useLastCallback(() => { if (isExpanded) { - startViewTransition(VTT_PROFILE_BUSINESS_HOURS_COLLAPSE, () => { - collapse(); - }); + collapse(); } else { - startViewTransition(VTT_PROFILE_BUSINESS_HOURS_EXPAND, () => { - expand(); - }); + expand(); } }); @@ -151,36 +145,34 @@ const BusinessHours = ({
- {isExpanded && ( -
- {Boolean(timezoneMinuteDifference) && ( -
- {oldLang(isMyTime ? 'BusinessHoursProfileSwitchMy' : 'BusinessHoursProfileSwitchLocal')} -
- )} -
- {DAYS.map((day) => ( - <> -
- {formatWeekday(oldLang, day === 6 ? 0 : day + 1)} -
-
- {workHours[day].map((segment) => ( -
{segment}
- ))} -
- - ))} -
-
- )} +
+ {Boolean(timezoneMinuteDifference) && ( +
+ {oldLang(isMyTime ? 'BusinessHoursProfileSwitchMy' : 'BusinessHoursProfileSwitchLocal')} +
+ )} +
+ {DAYS.map((day) => ( + <> +
+ {formatWeekday(oldLang, day === 6 ? 0 : day + 1)} +
+
+ {workHours[day].map((segment) => ( +
{segment}
+ ))} +
+ + ))} +
+
); }; diff --git a/src/components/common/profile/ChatExtra.tsx b/src/components/common/profile/ChatExtra.tsx index 2729f1e2b..7683ebfff 100644 --- a/src/components/common/profile/ChatExtra.tsx +++ b/src/components/common/profile/ChatExtra.tsx @@ -76,7 +76,6 @@ type OwnProps = { isOwnProfile?: boolean; isSavedDialog?: boolean; isInSettings?: boolean; - withIslands?: boolean; className?: string; style?: string; }; @@ -132,7 +131,6 @@ const ChatExtra = ({ className, style, isInSettings, - withIslands, canViewSubscribers, }: OwnProps & StateProps) => { const { @@ -392,17 +390,15 @@ const ChatExtra = ({ ); } - const Wrapper = withIslands ? Island : 'div'; - return (
{user && userFullInfo?.isUnofficialSecurityRisk && ( - +
{lang('UnofficialSecurityRisk', { peer: getPeerTitle(lang, user) })}
-
+ )} {personalChannel && (
@@ -410,7 +406,7 @@ const ChatExtra = ({ {oldLang('Subscribers', personalChannel.membersCount, 'i')} - + - +
)} - + {Boolean(formattedNumber?.length) && ( )} - +
); }; diff --git a/src/components/common/profile/ProfileInfo.module.scss b/src/components/common/profile/ProfileInfo.module.scss index 72a3774a7..52e4c4713 100644 --- a/src/components/common/profile/ProfileInfo.module.scss +++ b/src/components/common/profile/ProfileInfo.module.scss @@ -1,7 +1,7 @@ @use "../../../styles/mixins"; .root { - --profile-info-bg: var(--color-background); + --profile-info-bg: var(--color-background-secondary); --rating-outline-color: #000000; --rating-text-color: #000000; diff --git a/src/components/gili/layout/Island.module.scss b/src/components/gili/layout/Island.module.scss index 053574c23..42760363e 100644 --- a/src/components/gili/layout/Island.module.scss +++ b/src/components/gili/layout/Island.module.scss @@ -57,3 +57,8 @@ margin-top: 1rem; } } + +.outside { + padding-bottom: 0.5rem; + padding-inline: 0.5rem; +} diff --git a/src/components/gili/layout/Island.tsx b/src/components/gili/layout/Island.tsx index eb07661ba..cc23cc1a2 100644 --- a/src/components/gili/layout/Island.tsx +++ b/src/components/gili/layout/Island.tsx @@ -43,6 +43,24 @@ const IslandTitle = ({ className, children, ...otherProps }: OwnProps) => { ); }; +const IslandOutside = ({ + className, + children, + ...otherProps +}: OwnProps) => { + return ( +
+ {children} +
+ ); +}; + const IslandText = ({ className, children, ...otherProps }: OwnProps) => { return (
{ export default Island; export { + IslandOutside, IslandDescription, IslandTitle, IslandText, diff --git a/src/components/left/LeftColumn.scss b/src/components/left/LeftColumn.scss index 03e923ec2..89a1f139d 100644 --- a/src/components/left/LeftColumn.scss +++ b/src/components/left/LeftColumn.scss @@ -12,6 +12,12 @@ background-color: var(--color-background); + transition: background-color 150ms; + + &.secondary { + background-color: var(--color-background-secondary); + } + h3 { user-select: none; diff --git a/src/components/left/LeftColumn.tsx b/src/components/left/LeftColumn.tsx index dd0744640..c7e0e390c 100644 --- a/src/components/left/LeftColumn.tsx +++ b/src/components/left/LeftColumn.tsx @@ -11,7 +11,8 @@ import type { ReducerAction } from '../../hooks/useReducer'; import { type AnimationLevel, LeftColumnContent, SettingsScreens } from '../../types'; import { - selectCurrentChat, selectIsCurrentUserFrozen, selectIsForumPanelOpen, selectTabState, + selectCurrentChat, selectIsCurrentUserFrozen, selectIsForumPanelOpen, + selectPeerHasProfileBackground, selectTabState, } from '../../global/selectors'; import { selectSharedSettings } from '../../global/selectors/sharedState'; import { @@ -61,6 +62,7 @@ type StateProps = { archiveSettings: GlobalState['archiveSettings']; isArchivedStoryRibbonShown?: boolean; isAccountFrozen?: boolean; + hasProfileBackground?: boolean; }; enum ContentType { @@ -98,6 +100,7 @@ function LeftColumn({ archiveSettings, isArchivedStoryRibbonShown, isAccountFrozen, + hasProfileBackground, isFoldersSidebarShown, }: OwnProps & StateProps) { const { @@ -514,6 +517,7 @@ function LeftColumn({ foldersDispatch={foldersDispatch} animationLevel={animationLevel} shouldSkipTransition={shouldSkipHistoryAnimations} + hasProfileBackground={hasProfileBackground} onReset={handleReset} /> ); @@ -627,6 +631,8 @@ export default memo(withGlobal( archiveSettings, isArchivedStoryRibbonShown: isArchivedRibbonShown, isAccountFrozen, + hasProfileBackground: currentUserId + ? selectPeerHasProfileBackground(global, currentUserId) : undefined, contentKey: leftColumn.contentKey, settingsScreen: leftColumn.settingsScreen, }; diff --git a/src/components/left/settings/PremiumStatusItem.tsx b/src/components/left/settings/PremiumStatusItem.tsx index 85868c6f3..bd13ee676 100644 --- a/src/components/left/settings/PremiumStatusItem.tsx +++ b/src/components/left/settings/PremiumStatusItem.tsx @@ -7,6 +7,7 @@ import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import StarIcon from '../../common/icons/StarIcon'; +import Island, { IslandDescription } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; type OwnProps = { @@ -19,20 +20,19 @@ function PremiumStatusItem({ premiumSection }: OwnProps) { const handleOpenPremiumModal = useLastCallback(() => openPremiumModal({ initialSection: premiumSection })); return ( -
- } - onClick={handleOpenPremiumModal} - > - {lang('PrivacyLastSeenPremium')} - -

+ <> + + } + onClick={handleOpenPremiumModal} + > + {lang('PrivacyLastSeenPremium')} + + + {lang('lng_messages_privacy_premium_about')} -

-
+ + ); } diff --git a/src/components/left/settings/PrivacyMessages.tsx b/src/components/left/settings/PrivacyMessages.tsx index 8f843ef52..6af5dec7f 100644 --- a/src/components/left/settings/PrivacyMessages.tsx +++ b/src/components/left/settings/PrivacyMessages.tsx @@ -23,6 +23,7 @@ import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; import RadioGroup from '../../ui/RadioGroup'; import PremiumStatusItem from './PremiumStatusItem'; @@ -159,28 +160,27 @@ function PrivacyMessages({ : oldLang('Users', noPaidReactionsForUsersCount, 'i'); return ( -
-

+ <> + {lang('RemoveFeeTitle')} -

- { - openSettingsScreen({ screen: SettingsScreens.PrivacyNoPaidMessages }); - }} - > -
- {lang('ExceptionTitlePrivacyChargeForMessages')} - - { - itemSubtitle - } - -
-
-
+ + + { + openSettingsScreen({ screen: SettingsScreens.PrivacyNoPaidMessages }); + }} + > +
+ {lang('ExceptionTitlePrivacyChargeForMessages')} + + {itemSubtitle} + +
+
+
+ ); } @@ -195,34 +195,34 @@ function PrivacyMessages({ }, [shouldChargeForMessages, lang]); return ( - <> -
-

- {oldLang('PrivacyMessagesTitle')} -

+
+ + {oldLang('PrivacyMessagesTitle')} + + -

- {privacyDescription} -

-
+ + + {privacyDescription} + {selectedValue === 'charge_for_messages' && ( -
+ -
+ )} {canChangeChargeForMessages && selectedValue === 'charge_for_messages' && renderSectionNoPaidMessagesForUsers()} {!isCurrentUserPremium && selectedValue !== 'charge_for_messages' && } - +
); } diff --git a/src/components/left/settings/Settings.scss b/src/components/left/settings/Settings.scss index 6456a08c5..0f9197689 100644 --- a/src/components/left/settings/Settings.scss +++ b/src/components/left/settings/Settings.scss @@ -3,6 +3,14 @@ #Settings { height: 100%; + .chat-list { + padding-bottom: 0; + + @media (max-width: 600px) { + padding-block: 0; + } + } + .with-notch::before { top: var(--header-height); } @@ -15,11 +23,11 @@ .left-header { padding-right: 0.8125rem; - } - .self-profile .ProfileInfo { - margin: -0.5rem 0 0.75rem -0.5rem; - margin-inline-end: calc(min(var(--scrollbar-width) - 0.5rem, 0px)); + &:has(~ .scrolled), + &:has(~ .settings-fab-wrapper .scrolled) { + background-color: var(--color-background); + } } } @@ -43,7 +51,14 @@ .settings-content { overflow-y: scroll; + height: calc(100% - var(--header-height)); + padding: 1rem; + padding-top: 0; + + background-color: var(--color-background-secondary); + + @include mixins.adapt-padding-to-scrollbar(1rem); &.password-form .input-group.error label::first-letter { text-transform: uppercase; @@ -82,7 +97,9 @@ flex-direction: column; align-items: center; - padding: 0 1.5rem; + margin-bottom: 1rem; + padding-block: 0; + padding-inline: 1.5rem; text-align: center; @@ -105,21 +122,6 @@ } } -.settings-main-menu { - padding: 0.5rem; - - @include mixins.adapt-padding-to-scrollbar(0.5rem); - @include mixins.side-panel-section; - - .ListItem.narrow:not(.multiline) { - margin-bottom: 0; - - .ListItem-button { - min-height: 3.5rem; - } - } -} - .settings-range-value { display: inline-flex; align-items: center; @@ -137,8 +139,7 @@ } .settings-unlock-button { - margin-top: 1rem; - margin-inline: 1rem; + margin-top: 0.5rem; } .fluid-container { @@ -246,39 +247,6 @@ } } - &.blocked-list-item { - margin-bottom: 0.5rem; - - .ListItem-button { - align-items: center; - padding: 0.5rem; - text-align: left; - } - - .Avatar { - width: 3rem; - height: 3rem; - margin-right: 1rem; - } - - .contact-info { - overflow: hidden; - } - - .contact-name { - margin-bottom: 0.25rem; - font-size: 1rem; - font-weight: var(--font-weight-medium); - line-height: 1rem; - } - - .contact-phone { - font-size: 0.875rem; - line-height: 1rem; - color: var(--color-text-secondary); - } - } - &[dir="rtl"] { .multiline-item .date { float: left; @@ -314,18 +282,63 @@ } } +.settings-language-transition { + height: auto; + margin-top: 1rem; +} + .settings-picker { padding-block: 0; } +.settings-picker-islands { + padding: 1rem; + background-color: var(--color-background-secondary); +} + .settings-input { - padding: 0.5rem 1rem 0 1rem; + padding: 0.125rem; +} + +.settings-input > :last-child { + --input-group-margin: 0; } .settings-group { padding: 1rem 1.5rem; } +.ListItem.blocked-list-item { + .ListItem-button { + align-items: center; + padding: 0.5rem; + text-align: left; + } + + .Avatar { + width: 3rem; + height: 3rem; + margin-right: 1rem; + } + + .contact-info { + overflow: hidden; + } + + .contact-name { + margin-bottom: 0.25rem; + font-size: 1rem; + font-weight: var(--font-weight-medium); + line-height: 1rem; + } + + .contact-phone { + font-size: 0.875rem; + line-height: 1rem; + color: var(--color-text-secondary); + } +} + .settings-fab-wrapper { position: relative; height: calc(100% - var(--header-height)); diff --git a/src/components/left/settings/Settings.tsx b/src/components/left/settings/Settings.tsx index 186ad4b4b..752a75895 100644 --- a/src/components/left/settings/Settings.tsx +++ b/src/components/left/settings/Settings.tsx @@ -155,6 +155,7 @@ export type OwnProps = { foldersDispatch: FolderEditDispatch; animationLevel: AnimationLevel; shouldSkipTransition?: boolean; + hasProfileBackground?: boolean; onReset: (forceReturnToChatList?: true | Event) => void; }; @@ -166,6 +167,7 @@ const Settings: FC = ({ onReset, animationLevel, shouldSkipTransition, + hasProfileBackground, }) => { const { closeShareChatFolderModal, openSettingsScreen } = getActions(); @@ -176,7 +178,8 @@ const Settings: FC = ({ useScrollNotch({ containerRef, - selector: '.settings-content', + selector: '.Transition_slide-active .settings-content,' + + ' .Transition_slide-active .settings-main-scroll', }, [currentScreen]); const handleReset = useLastCallback((forceReturnToChatList?: true | Event) => { @@ -513,6 +516,7 @@ const Settings: FC = ({ currentScreen={currentScreen} onReset={handleReset} editedFolderId={foldersState.folderId} + hasProfileBackground={hasProfileBackground} /> {renderCurrentSectionContent(isScreenActive, activeKey)} diff --git a/src/components/left/settings/SettingsAcceptedGift.tsx b/src/components/left/settings/SettingsAcceptedGift.tsx index 284e9ed1f..21519a5c8 100644 --- a/src/components/left/settings/SettingsAcceptedGift.tsx +++ b/src/components/left/settings/SettingsAcceptedGift.tsx @@ -8,6 +8,7 @@ import { selectIsCurrentUserPremium } from '../../../global/selectors'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; import Switcher from '../../ui/Switcher'; @@ -89,54 +90,56 @@ const SettingsAcceptedGift = ({ }); return ( -
-

+ <> + {lang('PrivacyAcceptedGiftTitle')} -

- - {lang('PrivacyGiftLimitedEdition')} - - - - {lang('PrivacyGiftUnlimited')} - - - - {lang('PrivacyGiftUnique')} - - - - {lang('PrivacyGiftPremiumSubscription')} - - -

+ + + + {lang('PrivacyGiftLimitedEdition')} + + + + {lang('PrivacyGiftUnlimited')} + + + + {lang('PrivacyGiftUnique')} + + + + {lang('PrivacyGiftPremiumSubscription')} + + + + {lang('PrivacyAcceptedGiftInfo')} -

-
+ + ); }; diff --git a/src/components/left/settings/SettingsActiveSessions.tsx b/src/components/left/settings/SettingsActiveSessions.tsx index dd95aacbc..86bf103ae 100644 --- a/src/components/left/settings/SettingsActiveSessions.tsx +++ b/src/components/left/settings/SettingsActiveSessions.tsx @@ -15,6 +15,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; import useOldLang from '../../../hooks/useOldLang'; +import Island, { IslandTitle } from '../../gili/layout/Island'; import ConfirmDialog from '../../ui/ConfirmDialog'; import ListItem from '../../ui/ListItem'; import RadioGroup from '../../ui/RadioGroup'; @@ -141,76 +142,79 @@ const SettingsActiveSessions: FC = ({ function renderCurrentSession(session: ApiSession) { return ( -
-

+ <> + {lang('AuthSessionsCurrentSession')} -

- - -
- {session.deviceModel} - - {session.appName} - {' '} - {session.appVersion} - , - {' '} - {session.platform} - {' '} - {session.systemVersion} - - - {session.ip} - {' '} - - - {' '} - {getLocation(session)} - -
-
- - {hasOtherSessions && ( - - {lang('TerminateAllSessions')} + + + +
+ {session.deviceModel} + + {session.appName} + {' '} + {session.appVersion} + , + {' '} + {session.platform} + {' '} + {session.systemVersion} + + + {session.ip} + {' '} + - + {' '} + {getLocation(session)} + +
- )} -
+ + {hasOtherSessions && ( + + {lang('TerminateAllSessions')} + + )} + + ); } function renderOtherSessions(sessionHashes: string[]) { return ( -
-

+ <> + {lang('OtherSessions')} -

- - {sessionHashes.map(renderSession)} -
+ + + {sessionHashes.map(renderSession)} + + ); } function renderAutoTerminate() { return ( -
-

+ <> + {lang('TerminateOldSessionHeader')} -

- -

{lang('IfInactiveFor')}

- -
+ + +

{lang('IfInactiveFor')}

+ +
+ ); } diff --git a/src/components/left/settings/SettingsActiveWebsites.tsx b/src/components/left/settings/SettingsActiveWebsites.tsx index 81e321d70..c42033f3d 100644 --- a/src/components/left/settings/SettingsActiveWebsites.tsx +++ b/src/components/left/settings/SettingsActiveWebsites.tsx @@ -15,6 +15,7 @@ import useOldLang from '../../../hooks/useOldLang'; import Avatar from '../../common/Avatar'; import FullNameTitle from '../../common/FullNameTitle'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ConfirmDialog from '../../ui/ConfirmDialog'; import ListItem from '../../ui/ListItem'; import SettingsActiveWebsite from './SettingsActiveWebsite'; @@ -80,13 +81,14 @@ const SettingsActiveWebsites: FC = ({ function renderSessions(sessionHashes: string[]) { return ( -
-

+ <> + {lang('WebSessionsTitle')} -

- - {sessionHashes.map(renderSession)} -
+ + + {sessionHashes.map(renderSession)} + + ); } @@ -135,7 +137,7 @@ const SettingsActiveWebsites: FC = ({ return (
-
+ = ({ > {lang('AuthSessions.LogOutApplications')} -

- {lang('ClearOtherWebSessionsHelp')} -

-
+ + + {lang('ClearOtherWebSessionsHelp')} + {renderSessions(orderedHashes)} = ({ return (
{customEmojiSets && ( -
- -
- {customEmojiSets.map((stickerSet: ApiStickerSet) => ( - - ))} -
-

+ <> + + + + +

+ {customEmojiSets.map((stickerSet: ApiStickerSet) => ( + + ))} +
+ + {renderText(lang('EmojiBotInfo'), ['links'])} -

-
+ + )}
); diff --git a/src/components/left/settings/SettingsDataStorage.tsx b/src/components/left/settings/SettingsDataStorage.tsx index 22374369f..b8603bf03 100644 --- a/src/components/left/settings/SettingsDataStorage.tsx +++ b/src/components/left/settings/SettingsDataStorage.tsx @@ -11,6 +11,7 @@ import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; +import Island, { IslandTitle } from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import ListItem from '../../ui/ListItem'; import RangeSlider from '../../ui/RangeSlider'; @@ -84,7 +85,7 @@ const SettingsDataStorage = ({ const value = AUTODOWNLOAD_FILESIZE_MB_LIMITS.indexOf(autoLoadFileMaxSizeMb); return ( -
+
-

{title}

- - setSettingOption({ [`canAutoLoad${key}FromContacts`]: isChecked })} - /> - setSettingOption({ [`canAutoLoad${key}InPrivateChats`]: isChecked })} - /> - setSettingOption({ [`canAutoLoad${key}InGroups`]: isChecked })} - /> - setSettingOption({ [`canAutoLoad${key}InChannels`]: isChecked })} - /> - - {key === 'File' && renderContentSizeSlider()} -
+ <> + {title} + + setSettingOption({ [`canAutoLoad${key}FromContacts`]: isChecked })} + /> + setSettingOption({ [`canAutoLoad${key}InPrivateChats`]: isChecked })} + /> + setSettingOption({ [`canAutoLoad${key}InGroups`]: isChecked })} + /> + setSettingOption({ [`canAutoLoad${key}InChannels`]: isChecked })} + /> + {key === 'File' && renderContentSizeSlider()} + + ); } @@ -166,7 +163,7 @@ const SettingsDataStorage = ({ canAutoLoadFileInGroups, canAutoLoadFileInChannels, )} -
+ -
+
); }; diff --git a/src/components/left/settings/SettingsDoNotTranslate.module.scss b/src/components/left/settings/SettingsDoNotTranslate.module.scss index 72f3984ce..cf57f3ef8 100644 --- a/src/components/left/settings/SettingsDoNotTranslate.module.scss +++ b/src/components/left/settings/SettingsDoNotTranslate.module.scss @@ -5,5 +5,6 @@ .item { overflow: hidden; - min-height: 25rem; + flex: 1 1 auto; + padding-block: 0; } diff --git a/src/components/left/settings/SettingsDoNotTranslate.tsx b/src/components/left/settings/SettingsDoNotTranslate.tsx index fba7ca710..808ab640d 100644 --- a/src/components/left/settings/SettingsDoNotTranslate.tsx +++ b/src/components/left/settings/SettingsDoNotTranslate.tsx @@ -13,6 +13,8 @@ import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import ItemPicker, { type ItemPickerOption } from '../../common/pickers/ItemPicker'; +import Island from '../../gili/layout/Island'; +import InputText from '../../ui/InputText'; import styles from './SettingsDoNotTranslate.module.scss'; @@ -79,7 +81,16 @@ const SettingsDoNotTranslate = ({ return (
-
+ + setSearchQuery(e.currentTarget.value)} + placeholder={lang('Search')} + noMargin + /> + + -
+
); }; diff --git a/src/components/left/settings/SettingsEditProfile.tsx b/src/components/left/settings/SettingsEditProfile.tsx index 593b871bd..fc26a7d51 100644 --- a/src/components/left/settings/SettingsEditProfile.tsx +++ b/src/components/left/settings/SettingsEditProfile.tsx @@ -26,6 +26,8 @@ import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated'; import ManageUsernames from '../../common/ManageUsernames'; import SafeLink from '../../common/SafeLink'; import UsernameInput from '../../common/UsernameInput'; +import Island, { IslandDescription, IslandOutside, IslandTitle } from '../../gili/layout/Island'; +import Surface from '../../gili/layout/Surface'; import AvatarEditable from '../../ui/AvatarEditable'; import FloatingActionButton from '../../ui/FloatingActionButton'; import InputText from '../../ui/InputText'; @@ -218,28 +220,30 @@ const SettingsEditProfile = ({ const purchaseInfoLink = `${TME_LINK_PREFIX}${PURCHASE_USERNAME}`; return ( -

+ {(oldLang('lng_username_purchase_available')) .replace('{link}', '%PURCHASE_LINK%') .split('%') .map((s) => { return (s === 'PURCHASE_LINK' ? : s); })} -

+ ); } return (
-
-
+ + + + +
-
+
+ + {renderText(oldLang('lng_settings_about_bio'), ['br', 'simple_markdown'])} + -

- {renderText(oldLang('lng_settings_about_bio'), ['br', 'simple_markdown'])} -

-
- -
+ {lang('SettingsBirthday')} -

- {lang('BirthdayPrivacySuggestion', { - link: ( - - {lang('BirthdayPrivacySuggestionLink', - undefined, { withNodes: true, specialReplacement: NEXT_ARROW_REPLACEMENT })} - - ), - }, { withNodes: true })} -

-
- -
-

{oldLang('Username')}

+ + + {lang('BirthdayPrivacySuggestion', { + link: ( + + {lang('BirthdayPrivacySuggestionLink', + undefined, { withNodes: true, specialReplacement: NEXT_ARROW_REPLACEMENT })} + + ), + }, { withNodes: true })} + + {oldLang('Username')} +
- - {editUsernameError === USERNAME_PURCHASE_ERROR && renderPurchaseLink()} -

- {renderText(oldLang('UsernameHelp'), ['br', 'simple_markdown'])} -

- {editableUsername && ( -

- {oldLang('lng_username_link')} -
- - {TME_LINK_PREFIX} - {editableUsername} - -

- )} -
+ + {editUsernameError === USERNAME_PURCHASE_ERROR && renderPurchaseLink()} + + {renderText(oldLang('UsernameHelp'), ['br', 'simple_markdown'])} + + {editableUsername && ( + + {oldLang('lng_username_link')} +
+ + {TME_LINK_PREFIX} + {editableUsername} + +
+ )} {shouldRenderUsernamesManage && ( )} -
+

{lang('lng_settings_experimental_about')}

-
+
Login on Test Server
-
-
+ +
Vaporize this button
-
-
+ + setSharedSettingOption({ shouldAllowHttpTransport: !shouldAllowHttpTransport })} /> - setSharedSettingOption({ shouldForceHttpTransport: !shouldForceHttpTransport })} /> -
-
+ + setSharedSettingOption({ shouldCollectDebugLogs: !shouldCollectDebugLogs })} /> - setSharedSettingOption({ shouldDebugExportedSenders: !shouldDebugExportedSenders })} /> -
Download log
-
+
); }; diff --git a/src/components/left/settings/SettingsGeneral.tsx b/src/components/left/settings/SettingsGeneral.tsx index 59cb00a39..185931aa5 100644 --- a/src/components/left/settings/SettingsGeneral.tsx +++ b/src/components/left/settings/SettingsGeneral.tsx @@ -19,6 +19,7 @@ import useAppLayout from '../../../hooks/useAppLayout'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; +import Island, { IslandTitle } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; import RadioGroup from '../../ui/RadioGroup'; import RangeSlider from '../../ui/RangeSlider'; @@ -117,9 +118,8 @@ const SettingsGeneral: FC = ({ return (
-
-

{lang('Settings')}

- + {lang('Settings')} + = ({ value={messageTextSize} onChange={handleMessageTextSizeChange} /> - openSettingsScreen({ screen: SettingsScreens.GeneralChatBackground })} > {lang('ChatBackground')} -
+ -
-

- {lang('Theme')} -

+ {lang('Theme')} + -
+ -
-

- {lang('SettingsTimeFormat')} -

+ {lang('SettingsTimeFormat')} + -
+ {keyboardSendOptions && ( -
-

{lang('SettingsKeyboard')}

- - -
+ <> + {lang('SettingsKeyboard')} + + + + )}
); diff --git a/src/components/left/settings/SettingsGeneralBackground.scss b/src/components/left/settings/SettingsGeneralBackground.scss index 8379bbccb..a21fb2a87 100644 --- a/src/components/left/settings/SettingsGeneralBackground.scss +++ b/src/components/left/settings/SettingsGeneralBackground.scss @@ -1,13 +1,29 @@ @use "../../../styles/mixins"; .SettingsGeneralBackground { + padding-bottom: 0 !important; + .settings-wallpapers { + overflow: clip; display: grid; grid-auto-rows: 1fr; grid-template-columns: repeat(3, 1fr); gap: 0.0625rem; - @include mixins.side-panel-section; + margin: 1rem -1rem 0; + margin-inline: calc(min(var(--scrollbar-width) - 1rem, 0px)); + border-top-left-radius: var(--border-radius-island); + border-top-right-radius: var(--border-radius-island); + + > :first-child .media-inner, + > :first-child::after { + border-top-left-radius: var(--border-radius-island); + } + + > :nth-child(3) .media-inner, + > :nth-child(3)::after { + border-top-right-radius: var(--border-radius-island); + } } .Loading { diff --git a/src/components/left/settings/SettingsGeneralBackground.tsx b/src/components/left/settings/SettingsGeneralBackground.tsx index b1a41d2ef..beee03efa 100644 --- a/src/components/left/settings/SettingsGeneralBackground.tsx +++ b/src/components/left/settings/SettingsGeneralBackground.tsx @@ -19,6 +19,7 @@ import { openSystemFilesDialog } from '../../../util/systemFilesDialog'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useOldLang from '../../../hooks/useOldLang'; +import Island from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import ListItem from '../../ui/ListItem'; import Loading from '../../ui/Loading'; @@ -124,7 +125,7 @@ const SettingsGeneralBackground: FC = ({ return (
-
+ = ({ checked={Boolean(isBlurred)} onChange={handleWallPaperBlurChange} /> -
+ {loadedWallpapers ? (
diff --git a/src/components/left/settings/SettingsGeneralBackgroundColor.scss b/src/components/left/settings/SettingsGeneralBackgroundColor.scss index 0fdbdd399..b43b8c444 100644 --- a/src/components/left/settings/SettingsGeneralBackgroundColor.scss +++ b/src/components/left/settings/SettingsGeneralBackgroundColor.scss @@ -1,6 +1,8 @@ @use "../../../styles/mixins"; .SettingsGeneralBackgroundColor { + padding-bottom: 0 !important; + &:not(.is-dragging) .handle { transition: transform 300ms ease; } @@ -71,12 +73,16 @@ } .predefined-colors { + overflow: clip; display: grid; grid-auto-rows: 1fr; grid-template-columns: repeat(3, 1fr); gap: 0.0625rem; - @include mixins.side-panel-section; + margin: 1rem -1rem 0; + margin-inline: calc(min(var(--scrollbar-width) - 1rem, 0px)); + border-top-left-radius: var(--border-radius-island); + border-top-right-radius: var(--border-radius-island); } .predefined-color { @@ -84,6 +90,14 @@ box-shadow: inset 0 0 0 0 var(--color-background); transition: box-shadow 300ms ease; + &:nth-child(1) { + border-top-left-radius: var(--border-radius-island); + } + + &:nth-child(3) { + border-top-right-radius: var(--border-radius-island); + } + &.active { border: 0.125rem solid var(--color-primary); box-shadow: inset 0 0 0 0.3125rem var(--color-background); diff --git a/src/components/left/settings/SettingsGeneralBackgroundColor.tsx b/src/components/left/settings/SettingsGeneralBackgroundColor.tsx index 24816ca19..623d61506 100644 --- a/src/components/left/settings/SettingsGeneralBackgroundColor.tsx +++ b/src/components/left/settings/SettingsGeneralBackgroundColor.tsx @@ -20,6 +20,7 @@ import { pick } from '../../../util/iteratees'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; +import Island from '../../gili/layout/Island'; import InputText from '../../ui/InputText'; import './SettingsGeneralBackgroundColor.scss'; @@ -211,7 +212,7 @@ const SettingsGeneralBackground: FC = ({ return (
-
+
= ({
-
+
{PREDEFINED_COLORS.map((color) => (
void; }; const SettingsHeader: FC = ({ currentScreen, editedFolderId, + hasProfileBackground, onReset, }) => { const { @@ -286,7 +288,9 @@ const SettingsHeader: FC = ({ } return ( -
+
+ + + {lang('SettingsPasskeysFooter', { + link: ( + + {lang('SettingsPasskeysFooterLink', undefined, + { withNodes: true, specialReplacement: NEXT_ARROW_REPLACEMENT })} + + ), + }, { withNodes: true })} + = ({
-
- -
+ +
+ +
+
); }; diff --git a/src/components/left/settings/SettingsPerformance.tsx b/src/components/left/settings/SettingsPerformance.tsx index 6512c3fc0..c88332455 100644 --- a/src/components/left/settings/SettingsPerformance.tsx +++ b/src/components/left/settings/SettingsPerformance.tsx @@ -22,6 +22,7 @@ import { IS_BACKDROP_BLUR_SUPPORTED, IS_SNAP_EFFECT_SUPPORTED } from '../../../u import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import RangeSlider from '../../ui/RangeSlider'; @@ -168,24 +169,22 @@ function SettingsPerformance({ return (
-
-

- {lang('SettingsPerformanceSliderTitle')} -

-

- {lang('SettingsPerformanceSliderSubtitle')} -

- + + {lang('SettingsPerformanceSliderTitle')} + + -
- -
-

{lang('SettingsPerformanceGranularTitle')}

+ + + {lang('SettingsPerformanceSliderSubtitle')} + + {lang('SettingsPerformanceGranularTitle')} + {PERFORMANCE_OPTIONS.map(([sectionName, options], index) => { return (
); })} -
+
); } diff --git a/src/components/left/settings/SettingsPrivacy.tsx b/src/components/left/settings/SettingsPrivacy.tsx index 8644b2f3a..956ea7bdf 100644 --- a/src/components/left/settings/SettingsPrivacy.tsx +++ b/src/components/left/settings/SettingsPrivacy.tsx @@ -19,6 +19,7 @@ import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import StarIcon from '../../common/icons/StarIcon'; +import Island, { IslandTitle } from '../../gili/layout/Island'; import Button from '../../ui/Button'; import Checkbox from '../../ui/Checkbox'; import ListItem from '../../ui/ListItem'; @@ -196,11 +197,10 @@ const SettingsPrivacy = ({ return (
-
+ openSettingsScreen({ screen: SettingsScreens.PrivacyBlockedUsers })} > {oldLang('BlockedUsers')} @@ -210,7 +210,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: hasPasscode ? SettingsScreens.PasscodeEnabled : SettingsScreens.PasscodeDisabled, })} @@ -226,7 +225,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: hasPassword ? SettingsScreens.TwoFaEnabled : SettingsScreens.TwoFaDisabled, })} @@ -257,22 +255,19 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.ActiveWebsites })} > {oldLang('PrivacySettings.WebSessions')} {webAuthCount} )} -
- -
-

{oldLang('PrivacyTitle')}

+ + {oldLang('PrivacyTitle')} + openSettingsScreen({ screen: SettingsScreens.PrivacyPhoneNumber })} >
@@ -285,7 +280,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyLastSeen })} >
@@ -298,7 +292,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyProfilePhoto })} >
@@ -311,7 +304,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyBio })} >
@@ -324,7 +316,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyBirthday })} >
@@ -337,7 +328,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyGifts })} >
@@ -350,7 +340,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyForwarding })} >
@@ -363,7 +352,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyPhoneCall })} >
@@ -378,7 +366,6 @@ const SettingsPrivacy = ({ allowDisabledClick rightElement={isCurrentUserPremium && } className="no-icon" - onClick={() => openSettingsScreen({ screen: SettingsScreens.PrivacyVoiceMessages })} >
@@ -392,7 +379,6 @@ const SettingsPrivacy = ({ narrow rightElement={isCurrentUserPremium && } className="no-icon" - onClick={() => openSettingsScreen({ screen: SettingsScreens.PrivacyMessages })} >
@@ -408,7 +394,6 @@ const SettingsPrivacy = ({ openSettingsScreen({ screen: SettingsScreens.PrivacyGroupChats })} >
@@ -418,65 +403,68 @@ const SettingsPrivacy = ({
-
+ {canChangeSensitive && ( -
-

+ <> + {oldLang('lng_settings_sensitive_title')} -

- - {!isSensitiveEnabled && needAgeVideoVerification && ( - - )} -
+ + + + {!isSensitiveEnabled && needAgeVideoVerification && ( + + )} + + )} {canDisplayAutoarchiveSetting && ( -
-

+ <> + {oldLang('NewChatsFromNonContacts')} -

- -
+ + + + + )} -
-

- {oldLang('lng_settings_window_system')} -

+ + {oldLang('lng_settings_window_system')} + + -
+ -
-

- {lang('DeleteMyAccount')} -

+ + {lang('DeleteMyAccount')} + + -
+
); }; diff --git a/src/components/left/settings/SettingsPrivacyBlockedUsers.module.scss b/src/components/left/settings/SettingsPrivacyBlockedUsers.module.scss new file mode 100644 index 000000000..71b9295a8 --- /dev/null +++ b/src/components/left/settings/SettingsPrivacyBlockedUsers.module.scss @@ -0,0 +1,15 @@ +.surface { + overflow: hidden; + display: flex; + flex-direction: column; + height: 100%; +} + +.listIsland { + overflow: hidden; + flex: 0 1 auto; + + min-height: 0; + margin-bottom: 1rem; + padding: 0; +} diff --git a/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx b/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx index aa1833546..bac303649 100644 --- a/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx +++ b/src/components/left/settings/SettingsPrivacyBlockedUsers.tsx @@ -16,11 +16,15 @@ import useOldLang from '../../../hooks/useOldLang'; import Avatar from '../../common/Avatar'; import FullNameTitle from '../../common/FullNameTitle'; +import Island, { IslandDescription } from '../../gili/layout/Island'; +import Surface from '../../gili/layout/Surface'; import FloatingActionButton from '../../ui/FloatingActionButton'; import ListItem from '../../ui/ListItem'; import Loading from '../../ui/Loading'; import BlockUserModal from './BlockUserModal'; +import styles from './SettingsPrivacyBlockedUsers.module.scss'; + type OwnProps = { isActive?: boolean; onReset: () => void; @@ -118,25 +122,28 @@ const SettingsPrivacyBlockedUsers: FC = ({ return (
-
-
-

- {lang('BlockedUsersInfo')} -

-
+ + + {lang('BlockedUsersInfo')} + -
- {blockedIds?.length ? ( -
- {blockedIds.map((contactId, i) => renderContact(contactId, i, 0))} -
- ) : blockedIds && !blockedIds.length ? ( -
{lang('NoBlocked')}
- ) : ( - - )} -
-
+ +
+ {blockedIds?.length ? ( +
+ {blockedIds.map((contactId, i) => renderContact(contactId, i, 0))} +
+ ) : blockedIds && !blockedIds.length ? ( +
{lang('NoBlocked')}
+ ) : ( + + )} +
+
+ {canShowHideReadTime && ( -
- -

+ <> + + + + {renderText(lang('HideReadTimeInfo'), ['br'])} -

-
+ + )} -
+ } onClick={handleOpenPremiumModal} > {isCurrentUserPremium ? lang('PrivacyLastSeenPremiumForPremium') : lang('PrivacyLastSeenPremium')} -

- {isCurrentUserPremium - ? lang('PrivacyLastSeenPremiumInfoForPremium') - : lang('PrivacyLastSeenPremiumInfo')} -

-
+ + + {isCurrentUserPremium + ? lang('PrivacyLastSeenPremiumInfoForPremium') + : lang('PrivacyLastSeenPremiumInfo')} + ); }; diff --git a/src/components/left/settings/SettingsPrivacyPublicProfilePhoto.tsx b/src/components/left/settings/SettingsPrivacyPublicProfilePhoto.tsx index 5f12d4e4c..a9b24b34a 100644 --- a/src/components/left/settings/SettingsPrivacyPublicProfilePhoto.tsx +++ b/src/components/left/settings/SettingsPrivacyPublicProfilePhoto.tsx @@ -10,6 +10,7 @@ import useFlag from '../../../hooks/useFlag'; import useOldLang from '../../../hooks/useOldLang'; import Avatar from '../../common/Avatar'; +import Island, { IslandDescription } from '../../gili/layout/Island'; import ConfirmDialog from '../../ui/ConfirmDialog'; import ListItem from '../../ui/ListItem'; import SelectAvatar from '../../ui/SelectAvatar'; @@ -63,44 +64,46 @@ const SettingsPrivacyPublicProfilePhoto: FC = ({ }, []); return ( -
- - - {lang(currentUserFallbackPhoto - ? 'Privacy.ProfilePhoto.UpdatePublicPhoto' - : 'Privacy.ProfilePhoto.SetPublicPhoto')} - - {currentUserFallbackPhoto && ( + <> + } - onClick={openDeleteFallbackPhotoModal} - destructive + icon="camera-add" + onClick={handleOpenFileSelector} > - {lang(currentUserFallbackPhoto.isVideo - ? 'Privacy.ProfilePhoto.RemovePublicVideo' - : 'Privacy.ProfilePhoto.RemovePublicPhoto')} - + {lang(currentUserFallbackPhoto + ? 'Privacy.ProfilePhoto.UpdatePublicPhoto' + : 'Privacy.ProfilePhoto.SetPublicPhoto')} - )} -

+ {currentUserFallbackPhoto && ( + } + onClick={openDeleteFallbackPhotoModal} + destructive + > + {lang(currentUserFallbackPhoto.isVideo + ? 'Privacy.ProfilePhoto.RemovePublicVideo' + : 'Privacy.ProfilePhoto.RemovePublicPhoto')} + + + )} + + {lang('Privacy.ProfilePhoto.PublicPhotoInfo')} -

-
+ + ); }; diff --git a/src/components/left/settings/SettingsPrivacyVisibility.tsx b/src/components/left/settings/SettingsPrivacyVisibility.tsx index 8983b8261..d8ff8516b 100644 --- a/src/components/left/settings/SettingsPrivacyVisibility.tsx +++ b/src/components/left/settings/SettingsPrivacyVisibility.tsx @@ -14,6 +14,7 @@ import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import Icon from '../../common/icons/Icon'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; import RadioGroup from '../../ui/RadioGroup'; import Switcher from '../../ui/Switcher'; @@ -95,25 +96,27 @@ const SettingsPrivacyVisibility: FC = ({ return (
{screen === SettingsScreens.PrivacyGifts && ( -
- - {lang('PrivacyDisplayGiftsButton')} - - -

+ <> + + + {lang('PrivacyDisplayGiftsButton')} + + + + {lang('PrivacyDisplayGiftIconInChats', { icon: , gift: lang('PrivacyDisplayGift'), }, { withNodes: true, })} -

-
+ + )} -
-

{headerText}

+ {headerText} + - {descriptionText && ( -

{descriptionText}

- )} -
+ + {descriptionText && ( + {descriptionText} + )} {!isPremiumRequired && (primaryExceptionLists.shouldShowAllowed || primaryExceptionLists.shouldShowDenied) && ( -
-

+ <> + {oldLang('PrivacyExceptions')} -

- {primaryExceptionLists.shouldShowAllowed && ( - { - openSettingsScreen({ screen: allowedContactsScreen }); - }} - > -
- {oldLang('AlwaysAllow')} - {allowedString} -
-
- )} - {primaryExceptionLists.shouldShowDenied && ( - { - openSettingsScreen({ screen: deniedContactsScreen }); - }} - > -
- {oldLang('NeverAllow')} - {blockString} -
-
- )} -
+ + + {primaryExceptionLists.shouldShowAllowed && ( + { + openSettingsScreen({ screen: allowedContactsScreen }); + }} + > +
+ {oldLang('AlwaysAllow')} + {allowedString} +
+
+ )} + {primaryExceptionLists.shouldShowDenied && ( + { + openSettingsScreen({ screen: deniedContactsScreen }); + }} + > +
+ {oldLang('NeverAllow')} + {blockString} +
+
+ )} +
+ )} {isPremiumRequired && } diff --git a/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx b/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx index e98d9e8ed..ef8ce7641 100644 --- a/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx +++ b/src/components/left/settings/SettingsPrivacyVisibilityExceptionList.tsx @@ -183,7 +183,7 @@ const SettingsPrivacyVisibilityExceptionList: FC = ({ } return ( -
+
= ({ itemInputType="checkbox" withDefaultPadding withStatus + withIslands /> = ({ }, [setDefaultReaction]); return ( -
- -
+ + + + + ); }; diff --git a/src/components/left/settings/SettingsStickers.tsx b/src/components/left/settings/SettingsStickers.tsx index 3b89c1d52..5f1bb0477 100644 --- a/src/components/left/settings/SettingsStickers.tsx +++ b/src/components/left/settings/SettingsStickers.tsx @@ -24,6 +24,7 @@ import useOldLang from '../../../hooks/useOldLang'; import ReactionStaticEmoji from '../../common/reactions/ReactionStaticEmoji'; import StickerSetCard from '../../common/StickerSetCard'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import ListItem from '../../ui/ListItem'; @@ -93,7 +94,7 @@ const SettingsStickers: FC = ({ return (
-
+ = ({ /> openSettingsScreen({ screen: SettingsScreens.CustomEmoji })} icon="smile" > @@ -112,7 +112,6 @@ const SettingsStickers: FC = ({ openSettingsScreen({ screen: SettingsScreens.QuickReaction })} > = ({
{lang('DoubleTapSetting')}
)} -
-
-

- {lang('InstalledStickers.DynamicPackOrder')} -

+ + + + {lang('InstalledStickers.DynamicPackOrder')} + + -

- {lang('InstalledStickers.DynamicPackOrderInfo')} -

-
+ + + {lang('InstalledStickers.DynamicPackOrderInfo')} + + {stickerSets && ( -
-

+ <> + {lang('ChooseStickerMyStickerSets')} -

-
- {stickerSets.map((stickerSet: ApiStickerSet) => ( - - ))} -
-

+ + +

+ {stickerSets.map((stickerSet: ApiStickerSet) => ( + + ))} +
+ + {renderText(lang('StickersBotInfo'), ['links'])} -

-
+ + )}
); diff --git a/src/components/left/settings/folders/SettingsFolders.scss b/src/components/left/settings/folders/SettingsFolders.scss index 7865332a0..c9a8daf1d 100644 --- a/src/components/left/settings/folders/SettingsFolders.scss +++ b/src/components/left/settings/folders/SettingsFolders.scss @@ -123,7 +123,6 @@ gap: 0.75rem; align-items: center; - margin-inline: 1rem; padding: 0.125rem; } @@ -224,11 +223,19 @@ background-color: var(--accent-color); } +.settings-folders-header.settings-content-header { + padding-inline: 0; +} + .settings-folders-input-container { position: relative; display: flex; align-items: center; align-self: stretch; + + .input-group { + margin: 0.5rem; + } } .settings-folders-input-with-icon .form-control { @@ -236,11 +243,11 @@ } .settings-folders-icon-picker { - --custom-emoji-size: 2rem; + --custom-emoji-size: 1.5rem; position: absolute; - inset-inline-end: 0.5rem; - font-size: 2rem; + inset-inline-end: 1.5rem; + font-size: 1.5rem; color: var(--color-text-secondary); } diff --git a/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx b/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx index 11b1c3760..bbe4a55f4 100644 --- a/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx +++ b/src/components/left/settings/folders/SettingsFoldersChatFilters.tsx @@ -137,7 +137,7 @@ const SettingsFoldersChatFilters: FC = ({ } return ( -
+
= ({ isSearchable withDefaultPadding withPeerTypes + withIslands allowMultiple itemInputType="checkbox" onSelectedIdsChange={handleSelectedIdsChange} diff --git a/src/components/left/settings/folders/SettingsFoldersEdit.tsx b/src/components/left/settings/folders/SettingsFoldersEdit.tsx index 10b8687d8..dd0e95310 100644 --- a/src/components/left/settings/folders/SettingsFoldersEdit.tsx +++ b/src/components/left/settings/folders/SettingsFoldersEdit.tsx @@ -40,6 +40,8 @@ import FolderIcon from '../../../common/FolderIcon'; import GroupChatInfo from '../../../common/GroupChatInfo'; import Icon from '../../../common/icons/Icon'; import PrivateChatInfo from '../../../common/PrivateChatInfo'; +import Island, { IslandDescription, IslandOutside, IslandTitle } from '../../../gili/layout/Island'; +import Surface from '../../../gili/layout/Surface'; import FloatingActionButton from '../../../ui/FloatingActionButton'; import InputText from '../../../ui/InputText'; import ListItem from '../../../ui/ListItem'; @@ -381,8 +383,8 @@ const SettingsFoldersEdit: FC = ({ return (
-
-
+ + = ({ {lang('FilterIncludeInfo')}

)} -
+ = ({ />
)} -
-
+ + {!isOnlyInvites && ( -
+ <> {state.error && state.error === ERROR_NO_CHATS && ( -

+ {oldLang(state.error)} -

+ )} -

{lang('FilterInclude')}

+ {lang('FilterInclude')} + + + {lang('FilterAddChats')} + - - {lang('FilterAddChats')} - - - {renderChats('included')} -
+ {renderChats('included')} + + )} {!isOnlyInvites && !isEditingChatList && ( -
-

{lang('FilterExclude')}

+ <> + {lang('FilterExclude')} + + + {lang('FilterAddChats')} + - - {lang('FilterAddChats')} - - - {renderChats('excluded')} -
+ {renderChats('excluded')} + + )} -
-

- {lang('FilterColorTitle')} -
- {renderTextWithEntities({ - text: state.folder.title.text, - entities: state.folder.title.entities, - noCustomEmojiPlayback: state.folder.noTitleAnimations, - })} -
-

+ + {lang('FilterColorTitle')} +
+ {renderTextWithEntities({ + text: state.folder.title.text, + entities: state.folder.title.entities, + noCustomEmojiPlayback: state.folder.noTitleAnimations, + })} +
+
+
{FOLDER_COLORS.map((color) => (
-

- {lang('FilterColorHint')} -

-
- -
-

- {oldLang('FolderLinkScreen.Title')} -

+ + + {lang('FilterColorHint')} + + + {oldLang('FolderLinkScreen.Title')} + + = ({ ))} - -
-
+ + -
+ + )} -
- -
-

{lang('Filters')}

+ + {lang('Filters')} +
{userFolders?.length ? userFolders.map((folder, i) => { const isBlocked = i > maxFolders - 1; @@ -365,48 +366,49 @@ const SettingsFoldersMain = ({

) : }
-
+ {(recommendedChatFolders && Boolean(recommendedChatFolders.length)) && ( -
-

+ <> + {lang('FilterRecommended')} -

+ + + {recommendedChatFolders.map((folder) => ( + handleCreateFolderFromRecommended(folder)} + > +
+
+ + {renderTextWithEntities({ + text: folder.title.text, + entities: folder.title.entities, + noCustomEmojiPlayback: folder.noTitleAnimations, + })} + + {folder.description} +
- {recommendedChatFolders.map((folder) => ( - handleCreateFolderFromRecommended(folder)} - > -
-
- - {renderTextWithEntities({ - text: folder.title.text, - entities: folder.title.entities, - noCustomEmojiPlayback: folder.noTitleAnimations, - })} - - {folder.description} +
- - -
-
- ))} -
+
+ ))} +
+ )} -
+
{!isPremium && }
-
+ {!isMobile && ( -
-

{lang('TabsPosition')}

- - -
+ <> + {lang('TabsPosition')} + + + + )} -
+ ); }; diff --git a/src/components/left/settings/folders/SettingsShareChatlist.tsx b/src/components/left/settings/folders/SettingsShareChatlist.tsx index 8e1f0cfd0..f14145410 100644 --- a/src/components/left/settings/folders/SettingsShareChatlist.tsx +++ b/src/components/left/settings/folders/SettingsShareChatlist.tsx @@ -26,6 +26,7 @@ import useOldLang from '../../../../hooks/useOldLang'; import AnimatedIcon from '../../../common/AnimatedIcon'; import LinkField from '../../../common/LinkField'; import PeerPicker from '../../../common/pickers/PeerPicker'; +import Island, { IslandTitle } from '../../../gili/layout/Island'; import FloatingActionButton from '../../../ui/FloatingActionButton'; type OwnProps = { @@ -170,15 +171,18 @@ const SettingsShareChatlist: FC = ({ )}
- + {oldLang('InviteLink.InviteLink')} + + + -
+ = ({ withStatus itemInputType="checkbox" /> -
+ = ({

-
- -
+
); }; diff --git a/src/components/left/settings/passcode/SettingsPasscodeEnabled.tsx b/src/components/left/settings/passcode/SettingsPasscodeEnabled.tsx index 0a4c26957..e62dbdda3 100644 --- a/src/components/left/settings/passcode/SettingsPasscodeEnabled.tsx +++ b/src/components/left/settings/passcode/SettingsPasscodeEnabled.tsx @@ -10,6 +10,7 @@ import useHistoryBack from '../../../../hooks/useHistoryBack'; import useOldLang from '../../../../hooks/useOldLang'; import AnimatedIconWithPreview from '../../../common/AnimatedIconWithPreview'; +import Island from '../../../gili/layout/Island'; import ListItem from '../../../ui/ListItem'; import lockPreviewUrl from '../../../../assets/lock.png'; @@ -42,7 +43,7 @@ const SettingsPasscodeEnabled: FC = ({

-
+ = ({ > {lang('Passcode.TurnOff')} -
+
); }; diff --git a/src/components/left/settings/passcode/SettingsPasscodeStart.tsx b/src/components/left/settings/passcode/SettingsPasscodeStart.tsx index 2dd59662e..9efaaa5f0 100644 --- a/src/components/left/settings/passcode/SettingsPasscodeStart.tsx +++ b/src/components/left/settings/passcode/SettingsPasscodeStart.tsx @@ -43,9 +43,7 @@ const SettingsPasscodeStart: FC = ({

-
- -
+
); }; diff --git a/src/components/left/settings/twoFa/SettingsTwoFaCongratulations.tsx b/src/components/left/settings/twoFa/SettingsTwoFaCongratulations.tsx index deb6b29af..a91f7edea 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFaCongratulations.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFaCongratulations.tsx @@ -48,9 +48,7 @@ const SettingsTwoFaCongratulations: FC = ({

-
- -
+
); }; diff --git a/src/components/left/settings/twoFa/SettingsTwoFaEmailCode.tsx b/src/components/left/settings/twoFa/SettingsTwoFaEmailCode.tsx index e705bc33b..58959207c 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFaEmailCode.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFaEmailCode.tsx @@ -14,6 +14,7 @@ import useHistoryBack from '../../../../hooks/useHistoryBack'; import useOldLang from '../../../../hooks/useOldLang'; import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker'; +import Island from '../../../gili/layout/Island'; import InputText from '../../../ui/InputText'; import Loading from '../../../ui/Loading'; @@ -88,7 +89,7 @@ const SettingsTwoFaEmailCode: FC = ({ )}
-
+ = ({ onChange={handleInputChange} /> {isLoading && } -
+
); }; diff --git a/src/components/left/settings/twoFa/SettingsTwoFaEnabled.tsx b/src/components/left/settings/twoFa/SettingsTwoFaEnabled.tsx index 2d85a8a56..ec0344715 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFaEnabled.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFaEnabled.tsx @@ -11,6 +11,7 @@ import useHistoryBack from '../../../../hooks/useHistoryBack'; import useOldLang from '../../../../hooks/useOldLang'; import AnimatedIconWithPreview from '../../../common/AnimatedIconWithPreview'; +import Island from '../../../gili/layout/Island'; import ListItem from '../../../ui/ListItem'; import lockPreviewUrl from '../../../../assets/lock.png'; @@ -46,7 +47,7 @@ const SettingsTwoFaEnabled: FC = ({

-
+ = ({ > {lang('SetRecoveryEmail')} -
+
); }; diff --git a/src/components/left/settings/twoFa/SettingsTwoFaSkippableForm.tsx b/src/components/left/settings/twoFa/SettingsTwoFaSkippableForm.tsx index d81eda7d7..0de68ffff 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFaSkippableForm.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFaSkippableForm.tsx @@ -16,6 +16,7 @@ import useHistoryBack from '../../../../hooks/useHistoryBack'; import useOldLang from '../../../../hooks/useOldLang'; import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker'; +import Island from '../../../gili/layout/Island'; import Button from '../../../ui/Button'; import InputText from '../../../ui/InputText'; import Modal from '../../../ui/Modal'; @@ -107,8 +108,8 @@ const SettingsTwoFaSkippableForm: FC = ({ )}
-
-
+ + = ({
)} -
+
); }; diff --git a/src/components/left/settings/twoFa/SettingsTwoFaStart.tsx b/src/components/left/settings/twoFa/SettingsTwoFaStart.tsx index 55798de96..b868d4fa0 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFaStart.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFaStart.tsx @@ -42,9 +42,7 @@ const SettingsTwoFaStart: FC = ({

-
- -
+
); }; diff --git a/src/components/right/AddChatMembers.scss b/src/components/right/AddChatMembers.scss index 05e035c14..85848d566 100644 --- a/src/components/right/AddChatMembers.scss +++ b/src/components/right/AddChatMembers.scss @@ -1,11 +1,17 @@ .AddChatMembers { position: relative; + overflow: hidden; + height: 100%; - background: var(--color-background); + padding: 1rem; + + background: var(--color-background-secondary); &-inner { overflow: hidden; + display: flex; + flex-direction: column; height: 100%; } } diff --git a/src/components/right/AddChatMembers.tsx b/src/components/right/AddChatMembers.tsx index 121e4ead2..d7b3337f6 100644 --- a/src/components/right/AddChatMembers.tsx +++ b/src/components/right/AddChatMembers.tsx @@ -131,6 +131,7 @@ const AddChatMembers: FC = ({ onFilterChange={handleFilterChange} isSearchable withDefaultPadding + withIslands noScrollRestore={noPickerScrollRestore} allowMultiple withStatus diff --git a/src/components/right/CreateTopic.tsx b/src/components/right/CreateTopic.tsx index aa2c0a1f6..19b4c6cda 100644 --- a/src/components/right/CreateTopic.tsx +++ b/src/components/right/CreateTopic.tsx @@ -20,6 +20,7 @@ import useOldLang from '../../hooks/useOldLang'; import CustomEmojiPicker from '../common/CustomEmojiPicker'; import TopicIcon from '../common/TopicIcon'; +import Island from '../gili/layout/Island'; import FloatingActionButton from '../ui/FloatingActionButton'; import InputText from '../ui/InputText'; import Transition from '../ui/Transition'; @@ -114,7 +115,7 @@ const CreateTopic: FC = ({ return (
-
+ {lang('CreateTopicTitle')} = ({ disabled={isLoading} teactExperimentControlled /> -
-
+ + = ({ pickerListClassName="fab-padding-bottom" withDefaultTopicIcons /> -
+
= ({ {!topic && } {topic && ( <> -
+ {lang(isGeneral ? 'CreateGeneralTopicTitle' : 'CreateTopicTitle')} = ({ disabled={isLoading} teactExperimentControlled /> -
+ {!isGeneral && ( -
+ = ({ pickerListClassName="fab-padding-bottom" withDefaultTopicIcons /> -
+ )} )} diff --git a/src/components/right/ManageTopic.module.scss b/src/components/right/ManageTopic.module.scss index d07eeff52..6e422c6e3 100644 --- a/src/components/right/ManageTopic.module.scss +++ b/src/components/right/ManageTopic.module.scss @@ -5,37 +5,35 @@ position: relative; height: 100%; - background-color: var(--color-background); + background-color: var(--color-background-secondary); } .content { overflow: auto; display: flex; flex-direction: column; + height: 100%; -} - -.section { - display: flex; - flex-direction: column; - justify-content: center; - - @include mixins.side-panel-section; + padding: 1rem; } .general { - border-bottom: 0; box-shadow: none; } .top { + display: flex; + flex-direction: column; padding: 1rem 1.5rem; } .bottom { + display: flex; + flex-direction: column; flex-grow: 1; + min-height: 30rem; - margin-bottom: 0; + padding-bottom: 0; } .iconWrapper { diff --git a/src/components/right/Profile.module.scss b/src/components/right/Profile.module.scss index 046b7422f..256ea4a22 100644 --- a/src/components/right/Profile.module.scss +++ b/src/components/right/Profile.module.scss @@ -7,7 +7,7 @@ height: 100%; :global(.FloatingActionButton) { - z-index: 1; + z-index: 3; @include mixins.with-vt-type('rightColumn'); diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index dbbc34ef8..0458e62cb 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -1267,7 +1267,6 @@ const Profile = ({ chatOrUserId={profileId} isSavedDialog={isSavedDialog} isOwnProfile={isOwnProfile} - withIslands className={styles.chatExtraBlock} style={createVtnStyle('chatExtraBlock', true)} /> diff --git a/src/components/right/RightColumn.scss b/src/components/right/RightColumn.scss index 4f6d90b16..073e7797a 100644 --- a/src/components/right/RightColumn.scss +++ b/src/components/right/RightColumn.scss @@ -20,6 +20,8 @@ } > .Transition { + --slide-background-color: var(--color-background-secondary); + overflow: hidden; height: calc(100% - var(--header-height)); } @@ -33,7 +35,9 @@ } } - .Management .section > .ChatInfo { + .Management .section > .ChatInfo, + .Management > .custom-scroll > .ChatInfo, + .Management > .panel-content > .ChatInfo { margin: 1rem 0; padding: 0 1.5rem; text-align: center; diff --git a/src/components/right/RightColumn.tsx b/src/components/right/RightColumn.tsx index 5cda1fb88..77eba0632 100644 --- a/src/components/right/RightColumn.tsx +++ b/src/components/right/RightColumn.tsx @@ -1,11 +1,11 @@ import type { FC } from '@teact'; -import { memo, useEffect, useRef, useState } from '@teact'; +import { memo, useEffect, useLayoutEffect, useRef, useState } from '@teact'; import { getActions, withGlobal } from '../../global'; import type { AnimationLevel, ThreadId } from '../../types'; import { ManagementScreens, NewChatMembersProgress, ProfileState, RightColumnContent } from '../../types'; -import { ANIMATION_END_DELAY, MIN_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN } from '../../config'; +import { MIN_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN } from '../../config'; import { getIsSavedDialog } from '../../global/helpers'; import { selectAreActiveChatsLoaded, @@ -20,10 +20,12 @@ import captureEscKeyListener from '../../util/captureEscKeyListener'; import { resolveTransitionName } from '../../util/resolveTransitionName.ts'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; +import useFlag from '../../hooks/useFlag'; import useHistoryBack from '../../hooks/useHistoryBack'; import useLastCallback from '../../hooks/useLastCallback'; import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps'; import useScrollNotch from '../../hooks/useScrollNotch.ts'; +import useSyncEffect from '../../hooks/useSyncEffect'; import useWindowSize from '../../hooks/window/useWindowSize'; import Transition from '../ui/Transition'; @@ -63,7 +65,6 @@ type StateProps = { hasProfileBackground?: boolean; }; -const ANIMATION_DURATION = 450 + ANIMATION_END_DELAY; const MAIN_SCREENS_COUNT = Object.keys(RightColumnContent).length / 2; const MANAGEMENT_SCREENS_COUNT = Object.keys(ManagementScreens).length / 2; @@ -120,7 +121,6 @@ const RightColumn: FC = ({ const [selectedChatMemberId, setSelectedChatMemberId] = useState(); const [isPromotedByCurrentUser, setIsPromotedByCurrentUser] = useState(); const [isProfileExpanded, setIsProfileExpanded] = useState(false); - const [isProfileScrolled, setIsProfileScrolled] = useState(false); const isScrolledDown = profileState !== ProfileState.Profile; const isOpen = contentKey !== undefined; @@ -138,43 +138,57 @@ const RightColumn: FC = ({ const isCreatingTopic = contentKey === RightColumnContent.CreateTopic; const isEditingTopic = contentKey === RightColumnContent.EditTopic; const isOverlaying = windowWidth <= MIN_SCREEN_WIDTH_FOR_STATIC_RIGHT_COLUMN; + const isContentScrolledRef = useRef(false); - const headerBackground: 'regular' | 'secondary' = (() => { - if (isSavedMessages) return 'secondary'; - if (!isProfile) return 'regular'; + const hasStaticHeader = isSavedMessages || isAddingChatMembers || isCreatingTopic || isEditingTopic + || (isManagement && ( + managementScreen === ManagementScreens.GroupMembers + || managementScreen === ManagementScreens.ChatAdministrators + || managementScreen === ManagementScreens.GroupAddAdmins + )); + + const getHeaderBackground = useLastCallback((): 'regular' | 'secondary' => { + const isScrolled = isContentScrolledRef.current; + if (hasStaticHeader) return 'secondary'; + if (!isProfile) return isScrolled ? 'regular' : 'secondary'; if (isScrolledDown) return 'secondary'; - if (!isProfileScrolled && !isProfileExpanded && !hasProfileBackground) return 'secondary'; + if (!isScrolled && !isProfileExpanded && !hasProfileBackground) return 'secondary'; return 'regular'; - })(); + }); - const [shouldSkipTransition, setShouldSkipTransition] = useState(!isOpen); + const [headerBackground, setHeaderBackground] = useState<'regular' | 'secondary'>(getHeaderBackground); + + const handleContentScrolled = useLastCallback((isScrolled: boolean) => { + isContentScrolledRef.current = isScrolled; + setHeaderBackground(getHeaderBackground()); + }); + + const [isAnimating, startAnimating, stopAnimating] = useFlag(); + + useLayoutEffect(() => { + const elements = containerRef.current?.querySelectorAll( + ':scope .custom-scroll, :scope .panel-content', + ); + elements?.forEach((el) => { + el.scrollTop = 0; + }); + isContentScrolledRef.current = false; + setHeaderBackground(getHeaderBackground()); + }, [contentKey, managementScreen]); + + useSyncEffect(() => { + setHeaderBackground(getHeaderBackground()); + }, [isScrolledDown, isProfileExpanded, hasProfileBackground]); const renderingContentKey = useCurrentOrPrev(contentKey, true, !isChatSelected) ?? -1; useScrollNotch({ containerRef, selector: ':scope .custom-scroll, :scope .panel-content', - shouldHideTopNotch: isSavedMessages || (isProfile && isScrolledDown), + shouldHideTopNotch: isAnimating || isSavedMessages || hasStaticHeader || (isProfile && isScrolledDown), + onScrolled: handleContentScrolled, }, [contentKey, managementScreen, chatId, threadId]); - useEffect(() => { - if (!isProfile || isScrolledDown || isSavedMessages) { - setIsProfileScrolled(false); - return undefined; - } - - const scrollEl = containerRef.current?.querySelector('.custom-scroll'); - if (!scrollEl) return undefined; - - const handleProfileScroll = () => { - setIsProfileScrolled(scrollEl.scrollTop > 1); - }; - - handleProfileScroll(); - scrollEl.addEventListener('scroll', handleProfileScroll, { passive: true }); - return () => scrollEl.removeEventListener('scroll', handleProfileScroll); - }, [chatId, threadId, isProfile, isScrolledDown, isSavedMessages]); - const close = useLastCallback((shouldScrollUp = true) => { switch (contentKey) { case RightColumnContent.AddingMembers: @@ -278,12 +292,6 @@ const RightColumn: FC = ({ useEffect(() => (isOpen && chatId ? captureEscKeyListener(close) : undefined), [isOpen, close, chatId]); - useEffect(() => { - setTimeout(() => { - setShouldSkipTransition(!isOpen); - }, ANIMATION_DURATION); - }, [isOpen]); - useEffect(() => { if (nextManagementScreen) { setManagementScreen(nextManagementScreen); @@ -429,10 +437,12 @@ const RightColumn: FC = ({ /> = ({ return (
-
+ = ({ maxLength={maxBioLength} maxLengthIndicator={maxBioLength ? (maxBioLength - bio.length).toString() : undefined} /> -
-
+ +
{lang('BotEditIntro')} @@ -218,11 +219,11 @@ const ManageBot: FC = ({ {lang('BotChangeSettings')} -
+ {renderText(lang('BotManageInfo'), ['links'])} -
+
-
+
= ({ return (
-
- + +
= ({ /> )} -
-
+ + = ({ {lang('ChannelBlockedUsers')} {removedUsersCount} -
-
+ + {chat.isCreator ? lang('ChannelDelete') : lang('LeaveChannel')} -
+
= ({ return (
-
+ = ({ {lang('EventLog')} {lang(isChannel ? 'EventLogInfoDetailChannel' : 'EventLogInfoDetail')} -
- -
-

- {lang(isChannel - ? 'Channel.Management.AddModeratorHelp' - : 'Group.Management.AddModeratorHelp')} -

+ + + {lang(isChannel + ? 'Channel.Management.AddModeratorHelp' + : 'Group.Management.AddModeratorHelp')} + + {adminMembers.map((member) => ( = ({ ariaLabel={lang('Channel.Management.AddModerator')} iconName="add-user-filled" /> -
+ {canToggleSignatures && ( -
+
= ({ onChange={handleToggleProfiles} />
-

+ {lang('ChannelSignProfilesInfo')} -

+ )} -
+ )}
diff --git a/src/components/right/management/ManageChatPrivacyType.tsx b/src/components/right/management/ManageChatPrivacyType.tsx index da21b3921..f467b9238 100644 --- a/src/components/right/management/ManageChatPrivacyType.tsx +++ b/src/components/right/management/ManageChatPrivacyType.tsx @@ -25,6 +25,7 @@ import LinkField from '../../common/LinkField'; import ManageUsernames from '../../common/ManageUsernames'; import SafeLink from '../../common/SafeLink'; import UsernameInput from '../../common/UsernameInput'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ConfirmDialog from '../../ui/ConfirmDialog'; import FloatingActionButton from '../../ui/FloatingActionButton'; import ListItem from '../../ui/ListItem'; @@ -184,71 +185,77 @@ const ManageChatPrivacyType: FC = ({ const purchaseInfoLink = `${TME_LINK_PREFIX}${PURCHASE_USERNAME}`; return ( -

+ {(lang('lng_username_purchase_available')) .replace('{link}', '%PURCHASE_LINK%') .split('%') .map((s) => { return (s === 'PURCHASE_LINK' ? : s); })} -

+ ); } return (
-
-

{lang(`${langPrefix2}Type`)}

+ {lang(`${langPrefix2}Type`)} + -
+ {privacyType === 'private' ? ( -
- {privateInviteLink ? ( - <> - -

- {lang(`${langPrefix1}PrivateLinkHelp`)} -

- - - {lang('RevokeLink')} - - - - ) : ( - - )} -
+ <> + + {lang('InviteLink.InviteLink')} + + + {privateInviteLink ? ( + <> + + + {lang('RevokeLink')} + + + + ) : ( + + )} + + + {lang(`${langPrefix1}PrivateLinkHelp`)} + + ) : ( -
-
- -
+ <> + +
+ +
+
{error === USERNAME_PURCHASE_ERROR && renderPurchaseLink()} -

+ {lang(`${langPrefix2}.Username.CreatePublicLinkHelp`)} -

-
+ + )} {shouldRenderUsernamesManage && ( = ({ onEditUsername={handleUsernameChange} /> )} -
-

- {lang(isChannel ? 'ChannelVisibility.Forwarding.ChannelTitle' : 'ChannelVisibility.Forwarding.GroupTitle')} -

+ + {lang(isChannel ? 'ChannelVisibility.Forwarding.ChannelTitle' : 'ChannelVisibility.Forwarding.GroupTitle')} + + -

- {isChannel - ? lang('ChannelVisibility.Forwarding.ChannelInfo') - : lang('ChannelVisibility.Forwarding.GroupInfo')} -

-
+ + + {isChannel + ? lang('ChannelVisibility.Forwarding.ChannelInfo') + : lang('ChannelVisibility.Forwarding.GroupInfo')} +
= ({ return (
-
-

{lang(isChannel ? 'NoBlockedChannel2' : 'NoBlockedGroup2')}

- - {removedMembers.map((member) => ( - - - - ))} - {canDeleteMembers && ( - - )} - {chat && canDeleteMembers && ( - - )} -
+ {lang(isChannel ? 'NoBlockedChannel2' : 'NoBlockedGroup2')} + {Boolean(removedMembers.length) && ( + + {removedMembers.map((member) => ( + + + + ))} + + )}
+ {canDeleteMembers && ( + + )} + {chat && canDeleteMembers && ( + + )}
); }; diff --git a/src/components/right/management/ManageDiscussion.tsx b/src/components/right/management/ManageDiscussion.tsx index dc8a22aca..be6c49815 100644 --- a/src/components/right/management/ManageDiscussion.tsx +++ b/src/components/right/management/ManageDiscussion.tsx @@ -22,6 +22,7 @@ import AnimatedIconWithPreview from '../../common/AnimatedIconWithPreview'; import Avatar from '../../common/Avatar'; import GroupChatInfo from '../../common/GroupChatInfo'; import NothingFound from '../../common/NothingFound'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import ConfirmDialog from '../../ui/ConfirmDialog'; import ListItem from '../../ui/ListItem'; @@ -208,7 +209,7 @@ const ManageDiscussion: FC = ({ function renderDiscussionGroups() { return (
-

{lang('DiscussionChannelHelp')}

+ {lang('DiscussionChannelHelp')}
= ({ )}
-

{lang('DiscussionChannelHelp2')}

+ {lang('DiscussionChannelHelp2')} = ({ return (
-
+ = ({ /> {linkedChat && renderLinkedGroup()} {!linkedChat && renderDiscussionGroups()} -
+ {linkedChat && ( -
-

{lang('ChannelSettingsJoinTitle')}

-
- -
- {isJoinToSend && ( + <> + {lang('ChannelSettingsJoinTitle')} +
- )} -

+ {isJoinToSend && ( +

+ +
+ )} +
+ {isJoinToSend ? lang('ChannelSettingsJoinRequestInfo') : lang('ChannelSettingsJoinToSendInfo')} -

-
+ + )}
diff --git a/src/components/right/management/ManageGroup.tsx b/src/components/right/management/ManageGroup.tsx index a7d4bf933..778e8a027 100644 --- a/src/components/right/management/ManageGroup.tsx +++ b/src/components/right/management/ManageGroup.tsx @@ -28,6 +28,7 @@ import useLastCallback from '../../../hooks/useLastCallback'; import useMedia from '../../../hooks/useMedia'; import useOldLang from '../../../hooks/useOldLang'; +import Island, { IslandDescription } from '../../gili/layout/Island'; import AvatarEditable from '../../ui/AvatarEditable'; import Checkbox from '../../ui/Checkbox'; import ConfirmDialog from '../../ui/ConfirmDialog'; @@ -320,13 +321,13 @@ const ManageGroup: FC = ({ return (
-
- + +
= ({ inactive /> -
{lang('ForumToggleDescription')}
+ {lang('ForumToggleDescription')} )} -
-
+ + {lang('GroupMembers')} {formatInteger(chat.membersCount ?? 0)} @@ -455,12 +456,12 @@ const ManageGroup: FC = ({ />
)} -
-
+ + {lang('DeleteMega')} -
+
-
+ -

{lang('EditAdminWhatCanDo')}

+
+ {lang('EditAdminWhatCanDo')} + +
+ {lang('EditAdminUnavailable')} -

+
)} {!isChannel && ( @@ -469,7 +473,7 @@ const ManageGroupAdminRights = ({ {lang('EditAdminRemoveAdmin')} )} -
+
= ({ openChat, setUserSearchQuery, closeManagement, toggleParticipantsHidden, setNewChatMembersDialogState, toggleManagement, } = getActions(); - const lang = useOldLang(); + const oldLang = useOldLang(); + const lang = useLang(); const inputRef = useRef(); const containerRef = useRef(); @@ -182,7 +185,7 @@ const ManageGroupMembers: FC = ({ function getMemberContextAction(memberId: string): MenuItemContextAction[] | undefined { return memberId === currentUserId || !canDeleteMembers ? undefined : [{ - title: lang('lng_context_remove_from_group'), + title: oldLang('lng_context_remove_from_group'), icon: 'stop', handler: () => { setDeletingUserId(memberId); @@ -192,34 +195,37 @@ const ManageGroupMembers: FC = ({ function renderSearchField() { return ( -
+ -
+ ); } return ( -
- {noAdmins && renderSearchField()} -
+
+
+ {noAdmins && renderSearchField()} {canHideParticipants && !isChannel && ( -
- - {lang('ChannelHideMembers')} - - -

- {lang(areParticipantsHidden ? 'GroupMembers.MembersHiddenOn' : 'GroupMembers.MembersHiddenOff')} -

-
+ <> + + + {oldLang('ChannelHideMembers')} + + + + + {oldLang(areParticipantsHidden ? 'GroupMembers.MembersHiddenOn' : 'GroupMembers.MembersHiddenOff')} + + )} -
- {viewportIds?.length ? ( + {viewportIds?.length ? ( + = ({ handleMemberClick(id)} contextActions={getMemberContextAction(id)} withPortalForMenu @@ -241,22 +246,22 @@ const ManageGroupMembers: FC = ({ ))} - ) : !isSearching && viewportIds && !viewportIds.length ? ( - - ) : ( - - )} -
+ + ) : !isSearching && viewportIds && !viewportIds.length ? ( + + ) : ( + + )}
{canAddMembers && ( )} diff --git a/src/components/right/management/ManageGroupPermissions.tsx b/src/components/right/management/ManageGroupPermissions.tsx index c6031fbe2..faa30463f 100644 --- a/src/components/right/management/ManageGroupPermissions.tsx +++ b/src/components/right/management/ManageGroupPermissions.tsx @@ -27,6 +27,7 @@ import useManagePermissions from '../hooks/useManagePermissions'; import PaidMessagePrice from '../../common/paidMessage/PaidMessagePrice'; import PrivateChatInfo from '../../common/PrivateChatInfo'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import PermissionCheckboxList from '../../main/PermissionCheckboxList'; import FloatingActionButton from '../../ui/FloatingActionButton'; import ListItem from '../../ui/ListItem'; @@ -222,7 +223,6 @@ const ManageGroupPermissions: FC = ({ const arePermissionsChanged = isPriceForMessagesChanged || havePermissionChanged; const arePermissionsLoading = progress === ManagementProgress.InProgress || isLoading; - return (
= ({ + `--before-shift-height: ${BEFORE_ITEMS_COUNT * ITEM_HEIGHT}px;`} >
-
-

{lang('ChannelPermissionsHeader')}

+ {lang('ChannelPermissionsHeader')} + = ({ 'DropdownList', isMediaDropdownOpen && 'DropdownList--open', )} - shiftedClassName={buildClassName('part', isMediaDropdownOpen && 'shifted')} + shiftedClassName="part" /> -
+ {arePaidMessagesAvailable && ( -
+ {lang('GroupMessagesChargePrice')} = ({ checked={isPriceForMessagesOpen} /> -

- {lang('RightsChargeStarsAbout')} -

-
+ + )} + {arePaidMessagesAvailable && ( + + {lang('RightsChargeStarsAbout')} + )} {isPriceForMessagesOpen && ( -
+ -
+ )} -
+ = ({ {lang('ChannelBlockedUsers')} {removedUsersCount} -
- -
-

{lang('PrivacyExceptions')}

+ + {lang('PrivacyExceptions')} + = ({ /> ))} -
+
= ({ + `--before-shift-height: ${BEFORE_ITEMS_COUNT * ITEM_HEIGHT + BEFORE_USER_INFO_HEIGHT}px;`} >
-
+ -

{oldLang('UserRestrictionsCanDo')}

+ {oldLang('UserRestrictionsCanDo')} = ({ isMediaDropdownOpen && 'DropdownList--open', )} dropdownClassName="DropdownListTrap" - shiftedClassName={buildClassName('part', isMediaDropdownOpen && 'shifted')} + shiftedClassName="part" getControlIsDisabled={getControlIsDisabled} /> -
+ {!isFormFullyDisabled && ( -
{oldLang('UserRestrictionsBlock')} -
+ )}
diff --git a/src/components/right/management/ManageGroupUserPermissionsCreate.tsx b/src/components/right/management/ManageGroupUserPermissionsCreate.tsx index b3a6f90e4..062d0074c 100644 --- a/src/components/right/management/ManageGroupUserPermissionsCreate.tsx +++ b/src/components/right/management/ManageGroupUserPermissionsCreate.tsx @@ -9,9 +9,11 @@ import { isChatChannel, sortUserIds } from '../../../global/helpers'; import { selectChat, selectChatFullInfo } from '../../../global/selectors'; import useHistoryBack from '../../../hooks/useHistoryBack'; +import useLang from '../../../hooks/useLang'; import NothingFound from '../../common/NothingFound'; import PrivateChatInfo from '../../common/PrivateChatInfo'; +import Island from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; type OwnProps = { @@ -39,6 +41,8 @@ const ManageGroupUserPermissionsCreate: FC = ({ onClose, isActive, }) => { + const lang = useLang(); + useHistoryBack({ isActive, onBack: onClose, @@ -64,9 +68,9 @@ const ManageGroupUserPermissionsCreate: FC = ({ return (
-
- {memberIds ? ( - memberIds.map((id, i) => ( + {memberIds?.length ? ( + + {memberIds.map((id, i) => ( = ({ > - )) - ) : ( - - )} -
+ ))} + + ) : ( + + )}
); diff --git a/src/components/right/management/ManageInvite.tsx b/src/components/right/management/ManageInvite.tsx index 38d96fe45..13e7a8f77 100644 --- a/src/components/right/management/ManageInvite.tsx +++ b/src/components/right/management/ManageInvite.tsx @@ -16,6 +16,7 @@ import useOldLang from '../../../hooks/useOldLang'; import useSyncEffect from '../../../hooks/useSyncEffect'; import CalendarModal from '../../common/CalendarModal'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import Button from '../../ui/Button'; import Checkbox from '../../ui/Checkbox'; import FloatingActionButton from '../../ui/FloatingActionButton'; @@ -158,25 +159,25 @@ const ManageInvite: FC = ({ return (
-
+ -
-
+ + -

{lang('LinkNameHelp')}

-
-
-
{lang('LimitByPeriod')}
+ {lang('LinkNameHelp')} + + {lang('LimitByPeriod')} + = ({ {formatTime(lang, customExpireDate)} )} -

{lang('TimeLimitHelp')}

-
+ {lang('TimeLimitHelp')} + {!isRequestNeeded && ( -
-
{lang('LimitNumberOfUses')}
- ({ value: n.toString(), label: n })), - { - value: '0', - label: lang('NoLimit'), - }, - { - value: 'custom', - label: lang('lng_group_invite_usage_custom'), - }, - ]} - onChange={setSelectedUsageOption} - selected={selectedUsageOption} - /> - {selectedUsageOption === 'custom' && ( - + {lang('LimitNumberOfUses')} + + ({ value: n.toString(), label: n })), + { + value: '0', + label: lang('NoLimit'), + }, + { + value: 'custom', + label: lang('lng_group_invite_usage_custom'), + }, + ]} + onChange={setSelectedUsageOption} + selected={selectedUsageOption} /> - )} -

{lang('UsesLimitHelp')}

-
+ {selectedUsageOption === 'custom' && ( + + )} + {lang('UsesLimitHelp')} + + )} ; return ( -
-

{importers.length ? lang('PeopleJoined', usage) : lang('NoOneJoined')}

-

+ <> + {importers.length ? lang('PeopleJoined', usage) : lang('NoOneJoined')} + {!importers.length && ( - usageLimit ? lang('PeopleCanJoinViaLinkCount', usageLimit - usage) : lang('NoOneJoinedYet') + + {usageLimit ? lang('PeopleCanJoinViaLinkCount', usageLimit - usage) : lang('NoOneJoinedYet')} + )} {importers.map((importer) => { const joinTime = formatMediaDateTime(lang, importer.date * 1000, true); @@ -93,8 +96,8 @@ const ManageInviteInfo = ({ ); })} -

-
+ + ); }; @@ -103,9 +106,9 @@ const ManageInviteInfo = ({ if (!requesters && importers) return ; if (!requesters?.length) return undefined; return ( -
-

{isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}

-

+ <> + {isChannel ? lang('SubscribeRequests') : lang('MemberRequests')} + {requesters.map((requester) => ( ))} -

-
+ + ); }; @@ -128,35 +131,37 @@ const ManageInviteInfo = ({
{!invite && ( -

{lang('Loading')}

+ {lang('Loading')} )} {invite && ( <> -
+ {Boolean(expireDate) && ( -

+ {isExpired ? lang('ExpiredLink') : lang('LinkExpiresIn', `${formatFullDate(lang, expireDate)} ${formatTime(lang, expireDate)}`)} -

+ )} -
+ {adminId && ( -
-

{lang('LinkCreatedeBy')}

- + {lang('LinkCreatedeBy')} + + openChat({ id: adminId })} - > - - -
+ onClick={() => openChat({ id: adminId })} + > + + + + )} {renderImporters()} {renderRequesters()} diff --git a/src/components/right/management/ManageInvites.tsx b/src/components/right/management/ManageInvites.tsx index daabbbee9..bc6ebf535 100644 --- a/src/components/right/management/ManageInvites.tsx +++ b/src/components/right/management/ManageInvites.tsx @@ -26,6 +26,7 @@ import AnimatedIconWithPreview from '../../common/AnimatedIconWithPreview'; import Icon from '../../common/icons/Icon'; import LinkField from '../../common/LinkField'; import NothingFound from '../../common/NothingFound'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ConfirmDialog from '../../ui/ConfirmDialog'; import ListItem, { type MenuItemContextAction } from '../../ui/ListItem'; @@ -274,26 +275,33 @@ const ManageInvites: FC = ({ return (
-
+ -

{isChannel ? oldLang('PrimaryLinkHelpChannel') : oldLang('PrimaryLinkHelp')}

-
+ + {isChannel ? oldLang('PrimaryLinkHelpChannel') : oldLang('PrimaryLinkHelp')} + + {primaryInviteLink && ( -
- -
+ <> + + {chat?.usernames ? oldLang('PublicLink') : oldLang('lng_create_permanent_link_title')} + + + + + )} -
+ {oldLang('CreateNewLink')} @@ -314,11 +322,11 @@ const ManageInvites: FC = ({ ))} -

{oldLang('ManageLinksInfoHelp')}

-
+ + {oldLang('ManageLinksInfoHelp')} {revokedExportedInvites && Boolean(revokedExportedInvites.length) && ( -
-

{oldLang('RevokedLinks')}

+ + {oldLang('RevokedLinks')} = ({ ))} -
+ )}
= ({ return (
-
+ = ({
)} -
-
+ +

{!chat?.joinRequests ? lang('Loading') : chat.joinRequests.length ? lang('JoinRequests', chat.joinRequests.length) : lang('NoMemberRequests')} @@ -90,9 +91,9 @@ const ManageJoinRequests: FC = ({ )} {chat?.joinRequests?.length === 0 && ( -

+ {isChannel ? lang('NoSubscribeRequestsDescription') : lang('NoMemberRequestsDescription')} -

+ )} {chat?.joinRequests?.map(({ userId, about, date }) => ( = ({ key={userId} /> ))} -
+
= ({
{Boolean(localReactionsLimit && shouldShowReactionsLimit) && ( -
-

+ <> + {lang('MaximumReactionsHeader')} -

- -

+ + + + + {lang('ChannelReactions.MaxCount.Info')} -

-
+ + )} -
-

- {lang('AvailableReactions')} -

+ + {lang('AvailableReactions')} + + -

- {localEnabledReactions?.type === 'all' && lang('EnableAllReactionsInfo')} - {localEnabledReactions?.type === 'some' && lang('EnableSomeReactionsInfo')} - {!localEnabledReactions && lang('DisableReactionsInfo')} -

-
+ + + {localEnabledReactions?.type === 'all' && lang('EnableAllReactionsInfo')} + {localEnabledReactions?.type === 'some' && lang('EnableSomeReactionsInfo')} + {!localEnabledReactions && lang('DisableReactionsInfo')} + {localEnabledReactions?.type === 'some' && ( -
-

+ <> + {lang('OnlyAllowThisReactions')} -

- {availableActiveReactions?.map(({ reaction, title }) => ( -
- isSameReaction(reaction, r))} - label={( -
- - {title} -
- )} - withIcon - onChange={handleReactionChange} - /> -
- ))} -
+ + + {availableActiveReactions?.map(({ reaction, title }) => ( +
+ isSameReaction(reaction, r))} + label={( +
+ + {title} +
+ )} + withIcon + onChange={handleReactionChange} + /> +
+ ))} +
+ )}
diff --git a/src/components/right/management/ManageUser.tsx b/src/components/right/management/ManageUser.tsx index 0e49a5d48..5cdeb0d55 100644 --- a/src/components/right/management/ManageUser.tsx +++ b/src/components/right/management/ManageUser.tsx @@ -28,6 +28,7 @@ import useOldLang from '../../../hooks/useOldLang'; import Avatar from '../../common/Avatar'; import PrivateChatInfo from '../../common/PrivateChatInfo'; +import Island, { IslandDescription } from '../../gili/layout/Island'; import Checkbox from '../../ui/Checkbox'; import ConfirmDialog from '../../ui/ConfirmDialog'; import FloatingActionButton from '../../ui/FloatingActionButton'; @@ -227,14 +228,14 @@ const ManageUser: FC = ({ return (
-
- + +
= ({ noReplaceNewlines />
-

{lang('EditUserNoteHint')}

+
+ {lang('EditUserNoteHint')} +
= ({ onChange={handleNotificationChange} />
-
+ {canSetPersonalPhoto && ( -
- - {oldLang('UserInfo.SuggestPhoto', user.firstName)} - - - {oldLang('UserInfo.SetCustomPhoto', user.firstName)} - - {personalPhoto && ( - - )} - ripple - onClick={openResetPersonalPhotoDialog} - > - {oldLang('UserInfo.ResetCustomPhoto')} + <> + + + {oldLang('UserInfo.SuggestPhoto', user.firstName)} - )} -

{oldLang('UserInfo.CustomPhotoInfo', user.firstName)}

-
+ + {oldLang('UserInfo.SetCustomPhoto', user.firstName)} + + {personalPhoto && ( + + )} + ripple + onClick={openResetPersonalPhotoDialog} + > + {oldLang('UserInfo.ResetCustomPhoto')} + + )} + + {oldLang('UserInfo.CustomPhotoInfo', user.firstName)} + )} -
+ {oldLang('DeleteContact')} -
+
.custom-scroll { + & > .custom-scroll, + & > .panel-content { overflow-x: hidden; overflow-y: scroll; + height: 100%; + padding: 1rem; + + background-color: var(--color-background-secondary); + + @include mixins.adapt-padding-to-scrollbar(1rem); } .personal-photo { @@ -14,116 +21,58 @@ margin-right: 2rem; } - .section { - padding: 1rem 0.5rem; + .section-icon { + margin: 0 auto 2rem; + } - @include mixins.adapt-padding-to-scrollbar(0.5rem); - @include mixins.side-panel-section; + & > .custom-scroll > .ChatInfo, + & > .panel-content > .ChatInfo { + display: flex; + flex-direction: column; + align-items: center; - &.wide { - padding: 1.5rem; + margin-bottom: 1rem; + padding: 1rem 1.5rem; + + text-align: center; + } + + .ChatInfo .title h3 { + margin-bottom: 0; + } + + .ListItem { + .Reaction { + display: flex; + align-items: center; } - &:first-of-type { - padding-top: 1rem; + .ReactionStaticEmoji { + width: 1.5rem; + margin-right: 1.6875rem; } - &.no-border { - border-top: none; - } - - &.section-with-fab { - padding-bottom: 3.5rem; - } - - > .ChatInfo { - margin: 0 0 2rem !important; - - .title h3 { - margin-bottom: 0; + &.with-checkbox { + body.is-ios &::after, + body.is-android &::after { + bottom: -1rem; } } - .section-icon { - margin: 0 auto 2rem; - } - - .ListItem { - .Reaction { - display: flex; - align-items: center; - } - - .ReactionStaticEmoji { - width: 1.5rem; - margin-right: 1.6875rem; - } - - &.with-checkbox { - body.is-ios &::after, - body.is-android &::after { - bottom: -1rem; - } - } - - &.exceptions-member { - .ChatInfo .status { - white-space: pre-wrap; - } + &.exceptions-member { + .ChatInfo .status { + white-space: pre-wrap; } } + } - .section-heading { - position: relative; + .invite-link { + padding: 0 1rem; + } - padding-inline-start: 1rem; - - font-size: 1rem; - font-weight: var(--font-weight-semibold); - color: var(--color-text-secondary); - - &[dir="auto"] { - text-align: initial; - } - } - - .section-help { - padding: 0 1rem; - line-height: 1.375rem; - color: var(--color-text-secondary); - - &[dir="auto"] { - text-align: initial; - } - } - - .section-edit-info, - .section-info { - padding: 0 1rem; - font-size: 0.875rem; - color: var(--color-text-secondary); - } - - .section-edit-info { - margin-top: -0.875rem; - } - - .invite-link { - padding: 0 1rem; - } - - .section-info_push { - margin-top: 0.25rem; - } - - .input-admin-title { - margin-top: 0.875rem; - margin-inline: 1rem; - } - - &[dir="rtl"] { - text-align: right; - } + .input-admin-title { + margin-top: 0.875rem; + margin-inline: 1rem; } textarea.form-control { @@ -183,8 +132,27 @@ } } -.ManageGroupMembers { - padding: 0.5rem 1rem; +.ManageGroupMembers > .panel-content { + overflow: hidden; + display: flex; + flex-direction: column; + + .island-list { + overflow: hidden; + display: flex; + flex: 0 1 auto; + flex-direction: column; + + min-height: 0; + padding-block: 0; + + .picker-list { + overflow-x: hidden; + overflow-y: auto; + flex-grow: 1; + padding-block: 0.5rem; + } + } } .ManageInvites { @@ -311,6 +279,9 @@ width: 100%; height: 0; + /* stylelint-disable-next-line plugin/no-low-performance-animation-properties */ + transition: height 0.25s ease-in-out; + &::before { content: ""; @@ -333,27 +304,28 @@ } .without-bottom-shadow { - padding-bottom: 0; + --before-shift-height: 48px; + + position: relative; + overflow: hidden; + padding: 0.5rem 0.5rem 0; box-shadow: none; + + &.dropdown-open .DropdownListTrap { + height: var(--shift-height); + } } .part { - margin: 0 -1.5rem; - padding: 0 1.5rem 1rem; - - @include mixins.side-panel-section; + padding-bottom: 0.5rem; } .section, .part { position: relative; - transition: 0.25s ease-in-out transform; - - &.shifted { - transform: translateY(var(--shift-height)); - } } } .settings-edit { - padding: 0 1rem !important; + padding: 1.125rem !important; + padding-bottom: 0 !important; } diff --git a/src/components/right/statistics/BoostStatistics.module.scss b/src/components/right/statistics/BoostStatistics.module.scss index a7b270ee4..2496cd3c5 100644 --- a/src/components/right/statistics/BoostStatistics.module.scss +++ b/src/components/right/statistics/BoostStatistics.module.scss @@ -3,6 +3,8 @@ .root { overflow-x: hidden; overflow-y: scroll; + padding: 1rem; + background-color: var(--color-background-secondary); } .noResults { @@ -19,9 +21,6 @@ .section { padding: 1.5rem; - padding-inline-end: calc(1.5rem - var(--scrollbar-width)); - - @include mixins.side-panel-section; } .user :global(.status) { @@ -113,10 +112,6 @@ flex-direction: column-reverse; } -.giveawayButton { - margin: 0 -1rem 0.5rem; -} - .giveawayIcon { width: 2.75rem; height: 2.75rem; @@ -134,7 +129,3 @@ right: 0.5rem; transform: translate(0, -50%); } - -.boostInfo { - margin: 0 -1rem; -} diff --git a/src/components/right/statistics/BoostStatistics.tsx b/src/components/right/statistics/BoostStatistics.tsx index c6fcb3766..c4d3cd92a 100644 --- a/src/components/right/statistics/BoostStatistics.tsx +++ b/src/components/right/statistics/BoostStatistics.tsx @@ -22,6 +22,7 @@ import Icon from '../../common/icons/Icon'; import LinkField from '../../common/LinkField'; import PremiumProgress from '../../common/PremiumProgress'; import PrivateChatInfo from '../../common/PrivateChatInfo'; +import Island, { IslandDescription, IslandTitle } from '../../gili/layout/Island'; import ListItem from '../../ui/ListItem'; import Loading from '../../ui/Loading'; import Spinner from '../../ui/Spinner'; @@ -222,7 +223,7 @@ const BoostStatistics = ({ return ( handleBoosterClick(boost.userId)} > + {boostStatistics?.isLoadingBoosters ? ( + + ) : ( + + )} + {lang('ShowVotes', boostersToLoadCount, 'i')} + + ); + } + function renderContent() { let listToRender; if (tabType === 'boostList') { @@ -267,9 +287,10 @@ const BoostStatistics = ({ } return ( -
+ {listToRender?.map((boost) => renderBoostList(boost))} -
+ {renderLoadMore()} + ); } @@ -278,7 +299,7 @@ const BoostStatistics = ({ {!isLoaded && } {isLoaded && statsOverview && ( <> -
+ -
+ {statsOverview.prepaidGiveaways && ( -
-

+ <> + {lang('BoostingPreparedGiveaways')} -

- {statsOverview?.prepaidGiveaways?.map((prepaidGiveaway) => { - const isStarsGiveaway = 'stars' in prepaidGiveaway; + + + {statsOverview?.prepaidGiveaways?.map((prepaidGiveaway) => { + const isStarsGiveaway = 'stars' in prepaidGiveaway; - return ( - launchPrepaidGiveawayHandler(prepaidGiveaway)} - > -
-
- {isStarsGiveaway - ? ( - {lang('GiftStar')} - ) : ( - {lang('Giveaway')} - )} -
-
-

+ onClick={() => launchPrepaidGiveawayHandler(prepaidGiveaway)} + > +
+
{isStarsGiveaway - ? lang('Giveaway.Stars.Prepaid.Title', prepaidGiveaway.stars) - : lang('BoostingTelegramPremiumCountPlural', prepaidGiveaway.quantity)} -

-

- { - isStarsGiveaway ? lang('Giveaway.Stars.Prepaid.Desc', prepaidGiveaway.quantity) - : lang('PrepaidGiveawayMonths', prepaidGiveaway.months) - } -

-
-
-
- -
- {isStarsGiveaway ? prepaidGiveaway.boosts - : prepaidGiveaway.quantity * (giveawayBoostsPerPremium ?? GIVEAWAY_BOOST_PER_PREMIUM)} + ? ( + {lang('GiftStar')} + ) : ( + {lang('Giveaway')} + )} +
+
+

+ {isStarsGiveaway + ? lang('Giveaway.Stars.Prepaid.Title', prepaidGiveaway.stars) + : lang('BoostingTelegramPremiumCountPlural', prepaidGiveaway.quantity)} +

+

+ { + isStarsGiveaway ? lang('Giveaway.Stars.Prepaid.Desc', prepaidGiveaway.quantity) + : lang('PrepaidGiveawayMonths', prepaidGiveaway.months) + } +

+
+
+
+ +
+ {isStarsGiveaway ? prepaidGiveaway.boosts + : prepaidGiveaway.quantity * (giveawayBoostsPerPremium ?? GIVEAWAY_BOOST_PER_PREMIUM)} +
-
- - ); - })} -

{lang('BoostingSelectPaidGiveaway')}

-
+
+ ); + })} +
+ {lang('BoostingSelectPaidGiveaway')} + )} -
- {shouldDisplayGiftList ? ( + {shouldDisplayGiftList ? ( +
@@ -368,52 +391,45 @@ const BoostStatistics = ({
- ) : ( - <> -

- {lang('BoostingBoostsCount', boostStatistics?.boosts?.count)} -

- {!boostStatistics?.boosts?.list?.length && ( -
- {lang(isChannel ? 'NoBoostersHint' : 'NoBoostersGroupHint')} -
- )} - {boostStatistics?.boosts?.list?.map((boost) => renderBoostList(boost))} - - )} - {Boolean(boostersToLoadCount) && ( - - {boostStatistics?.isLoadingBoosters ? ( - - ) : ( - - )} - {lang('ShowVotes', boostersToLoadCount, 'i')} - - )} -
- + + ) : ( + <> + + {lang('BoostingBoostsCount', boostStatistics?.boosts?.count)} + + {!boostStatistics?.boosts?.list?.length ? ( + + {lang(isChannel ? 'NoBoostersHint' : 'NoBoostersGroupHint')} + + ) : ( + + {boostStatistics?.boosts?.list?.map((boost) => renderBoostList(boost))} + {renderLoadMore()} + + )} + + )} + {lang('LinkForBoosting')} + + + {isGiveawayAvailable && ( -
- - {lang('BoostingGetBoostsViaGifts')} - -

+ <> + + + {lang('BoostingGetBoostsViaGifts')} + + + {lang( isChannel ? 'BoostingGetMoreBoosts' : 'BoostingGetMoreBoostsGroup', )} -

-
+ + )} )} diff --git a/src/components/right/statistics/MessageStatistics.tsx b/src/components/right/statistics/MessageStatistics.tsx index cbff5cef4..23d17b17a 100644 --- a/src/components/right/statistics/MessageStatistics.tsx +++ b/src/components/right/statistics/MessageStatistics.tsx @@ -15,9 +15,11 @@ import { callApi } from '../../../api/gramjs'; import { isGraph } from './helpers/isGraph'; import useForceUpdate from '../../../hooks/useForceUpdate'; +import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; +import Island, { IslandTitle } from '../../gili/layout/Island'; import InfiniteScroll from '../../ui/InfiniteScroll'; import Loading from '../../ui/Loading'; import StatisticsMessagePublicForward from './StatisticsMessagePublicForward'; @@ -62,7 +64,8 @@ function MessageStatistics({ dcId, messageId, }: OwnProps & StateProps) { - const lang = useOldLang(); + const lang = useLang(); + const oldLang = useOldLang(); const containerRef = useRef(); const [isReady, setIsReady] = useState(false); const loadedChartsRef = useRef>(new Set()); @@ -141,10 +144,10 @@ function MessageStatistics({ LovelyChart.create( containerRef.current!.children[index] as HTMLElement, { - title: lang((GRAPH_TITLES as Record)[name]), + title: oldLang((GRAPH_TITLES as Record)[name]), ...zoomToken ? { onZoom: (x: number) => callApi('fetchStatisticsAsyncGraph', { token: zoomToken, x, dcId }), - zoomOutLabel: lang('Graph.ZoomOut'), + zoomOutLabel: oldLang('Graph.ZoomOut'), } : {}, ...graph, }, @@ -156,7 +159,7 @@ function MessageStatistics({ forceUpdate(); })(); }, [ - isReady, statistics, lang, chatId, messageId, loadStatisticsAsyncGraph, dcId, forceUpdate, + isReady, statistics, oldLang, chatId, messageId, loadStatisticsAsyncGraph, dcId, forceUpdate, ]); const handleLoadMore = useLastCallback(({ direction }: { direction: LoadMoreDirection }) => { @@ -174,11 +177,14 @@ function MessageStatistics({ key={`${chatId}-${messageId}`} className={buildClassName(styles.root, 'custom-scroll', isReady && styles.ready)} > - + {lang('StatisticOverview')} + + + {(!loadedChartsRef.current.size || !statistics.publicForwardsData) && } -
+
{GRAPHS.map((graph) => { const isGraphReady = loadedChartsRef.current.has(graph) && !errorChartsRef.current.has(graph); return ( @@ -189,18 +195,19 @@ function MessageStatistics({ {Boolean(statistics.publicForwards) && (
-

{lang('Stats.Message.PublicShares')}

- - - {(statistics.publicForwardsData as ApiMessagePublicForward[]).map((item) => ( - - ))} - + {lang('StatsMessagePublicShares')} + + + {(statistics.publicForwardsData as ApiMessagePublicForward[]).map((item) => ( + + ))} + +
)}
diff --git a/src/components/right/statistics/MonetizationStatistics.module.scss b/src/components/right/statistics/MonetizationStatistics.module.scss index 2dedfefdb..03a559f58 100644 --- a/src/components/right/statistics/MonetizationStatistics.module.scss +++ b/src/components/right/statistics/MonetizationStatistics.module.scss @@ -4,17 +4,16 @@ overflow-x: hidden; overflow-y: hidden; height: 100%; + padding: 1rem; } .graph { margin-bottom: 1rem; - border-bottom: 0.0625rem solid var(--color-borders); opacity: 1; transition: opacity 0.3s ease; &:last-of-type { margin-bottom: 0; - border-bottom: none; } &.hidden { @@ -23,21 +22,25 @@ } } +.charts { + display: flex; + flex-direction: column; +} + .ready { overflow-y: scroll !important; } -.section { +.balanceSection { display: flex; flex-direction: column; gap: 0.5rem; - - padding: 1rem 0.75rem; - border-bottom: 0.0625rem solid var(--color-borders); + padding: 1rem; } -.topText { - display: block; +.balanceTitle { + font-size: 0.9375rem; + font-weight: var(--font-weight-semibold); } .availableReward { diff --git a/src/components/right/statistics/MonetizationStatistics.tsx b/src/components/right/statistics/MonetizationStatistics.tsx index b91af5f7b..717dc98aa 100644 --- a/src/components/right/statistics/MonetizationStatistics.tsx +++ b/src/components/right/statistics/MonetizationStatistics.tsx @@ -20,6 +20,7 @@ import useOldLang from '../../../hooks/useOldLang'; import AboutMonetizationModal from '../../common/AboutMonetizationModal.async'; import Icon from '../../common/icons/Icon'; import SafeLink from '../../common/SafeLink'; +import Island, { IslandDescription } from '../../gili/layout/Island'; import Button from '../../ui/Button'; import ConfirmDialog from '../../ui/ConfirmDialog'; import Link from '../../ui/Link'; @@ -230,29 +231,31 @@ const MonetizationStatistics = ({ } return ( -
-
{topText}
+
+ {topText} - {oldLang('MonetizationProceedsTONInfo')}
- } - /> + + + + {oldLang('MonetizationProceedsTONInfo')} {!loadedChartsRef.current.size && } -
- {MONETIZATION_GRAPHS.filter(Boolean).map((graph) => ( -
- ))} -
+ +
+ {MONETIZATION_GRAPHS.filter(Boolean).map((graph) => ( +
+ ))} +
+ -
- {oldLang('lng_channel_earn_balance_title')} + +

{oldLang('lng_channel_earn_balance_title')}

{renderAvailableReward()} @@ -264,8 +267,8 @@ const MonetizationStatistics = ({ {oldLang('MonetizationWithdraw')} -
{rewardsText}
-
+ + {rewardsText} {statistics && ( - + + + )} {!loadedChartsRef.current.size && } -
+
{graphs.map((graph) => { const isGraphReady = loadedChartsRef.current.has(graph) && !errorChartsRef.current.has(graph); return ( @@ -219,7 +222,7 @@ const Statistics = ({
{Boolean((statistics as ApiChannelStatistics)?.recentPosts?.length) && ( -
+

{lang('ChannelStats.Recent.Header')}

{(statistics as ApiChannelStatistics).recentPosts.map((postStatistic) => { @@ -251,7 +254,7 @@ const Statistics = ({ return undefined; })} -
+ )}
); diff --git a/src/components/right/statistics/StatisticsOverview.module.scss b/src/components/right/statistics/StatisticsOverview.module.scss index 0d2f94798..3e5213652 100644 --- a/src/components/right/statistics/StatisticsOverview.module.scss +++ b/src/components/right/statistics/StatisticsOverview.module.scss @@ -1,7 +1,5 @@ .root { - margin-bottom: 1rem; - padding: 1rem 1.5rem; - border-bottom: 0.0625rem solid var(--color-borders); + padding: 0.5rem; } .header { @@ -41,12 +39,12 @@ } .tableHeading { - font-size: 0.9375rem; + font-size: 0.875rem; color: var(--color-text-secondary); } .tableValue { - font-size: 1.25rem; + font-size: 1rem; font-weight: var(--font-weight-medium); } diff --git a/src/components/ui/InputText.tsx b/src/components/ui/InputText.tsx index 97bfbd8fb..e7ca69604 100644 --- a/src/components/ui/InputText.tsx +++ b/src/components/ui/InputText.tsx @@ -26,6 +26,7 @@ type OwnProps = { title?: string; autoFocus?: boolean; teactExperimentControlled?: boolean; + noMargin?: boolean; inputMode?: 'text' | 'none' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'; onChange?: (e: ChangeEvent) => void; onInput?: (e: FormEvent) => void; @@ -54,6 +55,7 @@ const InputText = ({ title, autoFocus, teactExperimentControlled, + noMargin, onChange, onInput, onKeyPress, @@ -71,6 +73,7 @@ const InputText = ({ disabled && 'disabled', readOnly && 'disabled', labelText && 'with-label', + noMargin && 'no-margin', className, ); diff --git a/src/components/ui/Transition.scss b/src/components/ui/Transition.scss index 0670afb5f..b3c4bb9e4 100644 --- a/src/components/ui/Transition.scss +++ b/src/components/ui/Transition.scss @@ -163,11 +163,11 @@ } &-slideFadeAndroid { - --background-color: var(--color-background); + --slide-background-color: var(--color-background); > .Transition_slide { z-index: 0; - background: var(--background-color); + background: var(--slide-background-color); } > .Transition_slide-to { @@ -179,11 +179,11 @@ } &-slideFadeAndroidBackwards { - --background-color: var(--color-background); + --slide-background-color: var(--color-background); > .Transition_slide { z-index: 0; - background: var(--background-color); + background: var(--slide-background-color); } > .Transition_slide-from { @@ -277,12 +277,12 @@ } &-slideLayers { - --background-color: var(--color-background); + --slide-background-color: var(--color-background); background: black !important; > .Transition_slide { - background: var(--background-color); + background: var(--slide-background-color); } > .Transition_slide-to { @@ -296,12 +296,12 @@ } &-slideLayersBackwards { - --background-color: var(--color-background); + --slide-background-color: var(--color-background); background: black !important; > .Transition_slide { - background: var(--background-color); + background: var(--slide-background-color); } > .Transition_slide-to { @@ -317,8 +317,10 @@ } &-pushSlide { + --slide-background-color: var(--color-background); + > .Transition_slide { - background: var(--color-background); + background: var(--slide-background-color); } > .Transition_slide-from { @@ -343,8 +345,10 @@ } &-pushSlideBackwards { + --slide-background-color: var(--color-background); + > .Transition_slide { - background: var(--color-background); + background: var(--slide-background-color); } > .Transition_slide-to { diff --git a/src/hooks/useScrollNotch.ts b/src/hooks/useScrollNotch.ts index 183782d56..d9e628fb1 100644 --- a/src/hooks/useScrollNotch.ts +++ b/src/hooks/useScrollNotch.ts @@ -13,11 +13,13 @@ const useScrollNotch = ({ selector, isBottomNotch, shouldHideTopNotch, + onScrolled, }: { containerRef: ElementRef; selector: string; isBottomNotch?: boolean; shouldHideTopNotch?: boolean; + onScrolled?: (isScrolled: boolean) => void; }, deps: unknown[]) => { useLayoutEffect(() => { const elements = containerRef.current?.querySelectorAll(selector); @@ -29,6 +31,8 @@ const useScrollNotch = ({ const { scrollHeight, scrollTop, clientHeight } = target; const isAtEnd = scrollHeight - scrollTop - clientHeight < SCROLL_THRESHOLD; + onScrolled?.(isScrolled); + requestMutation(() => { if (!shouldHideTopNotch) { toggleExtraClass(target, 'scrolled', isScrolled); @@ -63,13 +67,18 @@ const useScrollNotch = ({ useEffect(() => { const elements = containerRef.current?.querySelectorAll(selector); - if (!elements?.length) return undefined; + if (!elements?.length) { + onScrolled?.(false); + return undefined; + } elements.forEach((el) => { const isScrolled = el.scrollTop > 0; const { scrollHeight, scrollTop, clientHeight } = el; const isAtEnd = scrollHeight - scrollTop - clientHeight < SCROLL_THRESHOLD; + onScrolled?.(isScrolled); + requestMutation(() => { if (!shouldHideTopNotch) { toggleExtraClass(el, 'scrolled', isScrolled); diff --git a/src/lib/lovely-chart/styles/_buttons.scss b/src/lib/lovely-chart/styles/_buttons.scss index 3abae9d46..49d843701 100644 --- a/src/lib/lovely-chart/styles/_buttons.scss +++ b/src/lib/lovely-chart/styles/_buttons.scss @@ -15,6 +15,7 @@ text-decoration: none; background-color: transparent; + transition: opacity 150ms ease; &:hover { @@ -77,7 +78,6 @@ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -256 1792 1792' version='1.1'%0A%3E%3Cg transform='matrix(1,0,0,-1,7.5932203,1217.0847)' id='g3003'%3E%3Cpath d='m 1671,970 q 0,-40 -28,-68 L 919,178 783,42 Q 755,14 715,14 675,14 647,42 L 511,178 149,540 q -28,28 -28,68 0,40 28,68 l 136,136 q 28,28 68,28 40,0 68,-28 l 294,-295 656,657 q 28,28 68,28 40,0 68,-28 l 136,-136 q 28,-28 28,-68 z' style='fill:white'/%3E%3C/g%3E%3C/svg%3E"); background-size: 100%; } - } .lovely-chart--button-label { diff --git a/src/lib/lovely-chart/styles/_common.scss b/src/lib/lovely-chart/styles/_common.scss index 6fc98d0f6..02fdcf59a 100644 --- a/src/lib/lovely-chart/styles/_common.scss +++ b/src/lib/lovely-chart/styles/_common.scss @@ -12,6 +12,16 @@ -webkit-user-select: none; user-select: none; + position: relative; + + overflow: hidden; + + font: 300 13px '-apple-system', 'HelveticaNeue', Helvetica, Arial, sans-serif; + color: #222222; + text-align: left; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + html.theme-dark & { --background-color: #242F3E; --text-color: #ffffff; @@ -24,16 +34,6 @@ --minimap-limit-color: #BFC0C2; } - position: relative; - - overflow: hidden; - - font: 300 13px '-apple-system', 'HelveticaNeue', Helvetica, Arial, sans-serif; - color: #222222; - text-align: left; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - // &.lovely-chart--state-invisible > * { // display: none; // } diff --git a/src/lib/lovely-chart/styles/_minimap.scss b/src/lib/lovely-chart/styles/_minimap.scss index 1fb4da892..c4ea762be 100644 --- a/src/lib/lovely-chart/styles/_minimap.scss +++ b/src/lib/lovely-chart/styles/_minimap.scss @@ -3,7 +3,7 @@ overflow: hidden; - margin: 0 10px 16px 10px; + margin: 0 10px 10px 10px; border-radius: 6px; opacity: 1; @@ -62,30 +62,28 @@ } .lovely-chart--minimap-limit-mask { - display: flex; - align-items: center; - justify-content: center; + pointer-events: none; position: absolute; top: 0; left: 0; - height: 100%; - border-radius: 6px 0 0 6px; + display: flex; + align-items: center; + justify-content: center; + + height: 100%; border-right: 2px dashed var(--minimap-limit-color); + border-radius: 6px 0 0 6px; color: var(--minimap-limit-color); - pointer-events: none; - - backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); + backdrop-filter: blur(4px); &.lovely-chart--state-interactive { - cursor: var(--custom-cursor, pointer); - pointer-events: auto; - + cursor: var(--custom-cursor, pointer); transition: opacity 200ms ease; &:hover { diff --git a/src/lib/lovely-chart/styles/_tools.scss b/src/lib/lovely-chart/styles/_tools.scss index 472af46fa..441dc49b9 100644 --- a/src/lib/lovely-chart/styles/_tools.scss +++ b/src/lib/lovely-chart/styles/_tools.scss @@ -1,5 +1,5 @@ .lovely-chart--tools { - padding: 0 10px 16px 10px; + padding: 0 10px 0 10px; opacity: 1; transition: opacity 400ms ease; diff --git a/src/styles/_forms.scss b/src/styles/_forms.scss index e0367736c..998d228af 100644 --- a/src/styles/_forms.scss +++ b/src/styles/_forms.scss @@ -14,7 +14,11 @@ .input-group { position: relative; - margin-bottom: 1.125rem; + margin-bottom: var(--input-group-margin, 1.125rem); + + &.no-margin { + margin-bottom: 0; + } label { pointer-events: none;