mirror of
https://github.com/danog/telegram-tt.git
synced 2024-12-12 00:59:52 +01:00
Settings: New design for self profile (#1373)
This commit is contained in:
parent
f039f69331
commit
ad36326c83
@ -12,7 +12,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isChatPrivate, isUserRightBanned, selectIsChatMuted,
|
getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isChatPrivate, isUserRightBanned, selectIsChatMuted,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import renderText from '../common/helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
import { pick } from '../../util/iteratees';
|
import { pick } from '../../util/iteratees';
|
||||||
import { copyTextToClipboard } from '../../util/clipboard';
|
import { copyTextToClipboard } from '../../util/clipboard';
|
||||||
import { formatPhoneNumberWithCode } from '../../util/phoneNumber';
|
import { formatPhoneNumberWithCode } from '../../util/phoneNumber';
|
||||||
@ -118,6 +118,7 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
<span className="subtitle">{lang('SetUrlPlaceholder')}</span>
|
<span className="subtitle">{lang('SetUrlPlaceholder')}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
|
{!forceShowSelf && (
|
||||||
<ListItem icon="unmute" ripple onClick={handleNotificationChange}>
|
<ListItem icon="unmute" ripple onClick={handleNotificationChange}>
|
||||||
<span>{lang('Notifications')}</span>
|
<span>{lang('Notifications')}</span>
|
||||||
<Switcher
|
<Switcher
|
||||||
@ -127,6 +128,7 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
inactive
|
inactive
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -159,4 +159,25 @@
|
|||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.self {
|
||||||
|
margin: 0 -.5rem .75rem;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.ghost {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev-avatar-media {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
padding-bottom: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
line-height: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,13 +12,14 @@ import { selectChat, selectUser } from '../../modules/selectors';
|
|||||||
import {
|
import {
|
||||||
getUserFullName, getUserStatus, isChatChannel, isUserOnline,
|
getUserFullName, getUserStatus, isChatChannel, isUserOnline,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import renderText from '../common/helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
import { pick } from '../../util/iteratees';
|
import { pick } from '../../util/iteratees';
|
||||||
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
||||||
|
import buildClassName from '../../util/buildClassName';
|
||||||
import usePhotosPreload from './hooks/usePhotosPreload';
|
import usePhotosPreload from './hooks/usePhotosPreload';
|
||||||
import useLang from '../../hooks/useLang';
|
import useLang from '../../hooks/useLang';
|
||||||
|
|
||||||
import VerifiedIcon from '../common/VerifiedIcon';
|
import VerifiedIcon from './VerifiedIcon';
|
||||||
import ProfilePhoto from './ProfilePhoto';
|
import ProfilePhoto from './ProfilePhoto';
|
||||||
import Transition from '../ui/Transition';
|
import Transition from '../ui/Transition';
|
||||||
|
|
||||||
@ -35,15 +36,16 @@ type StateProps = {
|
|||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
animationLevel: 0 | 1 | 2;
|
animationLevel: 0 | 1 | 2;
|
||||||
serverTimeOffset: number;
|
serverTimeOffset: number;
|
||||||
} & Pick<GlobalState, 'lastSyncTime'>;
|
} & Pick<GlobalState, 'connectionState'>;
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'openMediaViewer'>;
|
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'openMediaViewer'>;
|
||||||
|
|
||||||
const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||||
|
forceShowSelf,
|
||||||
user,
|
user,
|
||||||
chat,
|
chat,
|
||||||
isSavedMessages,
|
isSavedMessages,
|
||||||
lastSyncTime,
|
connectionState,
|
||||||
animationLevel,
|
animationLevel,
|
||||||
loadFullUser,
|
loadFullUser,
|
||||||
openMediaViewer,
|
openMediaViewer,
|
||||||
@ -69,10 +71,10 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lastSyncTime && userId) {
|
if (connectionState === 'connectionStateReady' && userId && !forceShowSelf) {
|
||||||
loadFullUser({ userId });
|
loadFullUser({ userId });
|
||||||
}
|
}
|
||||||
}, [userId, loadFullUser, lastSyncTime]);
|
}, [userId, loadFullUser, connectionState, forceShowSelf]);
|
||||||
|
|
||||||
usePhotosPreload(user || chat, photos, currentPhotoIndex);
|
usePhotosPreload(user || chat, photos, currentPhotoIndex);
|
||||||
|
|
||||||
@ -80,9 +82,9 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
openMediaViewer({
|
openMediaViewer({
|
||||||
avatarOwnerId: userId || chatId,
|
avatarOwnerId: userId || chatId,
|
||||||
profilePhotoIndex: currentPhotoIndex,
|
profilePhotoIndex: currentPhotoIndex,
|
||||||
origin: MediaViewerOrigin.ProfileAvatar,
|
origin: forceShowSelf ? MediaViewerOrigin.SettingsAvatar : MediaViewerOrigin.ProfileAvatar,
|
||||||
});
|
});
|
||||||
}, [openMediaViewer, userId, chatId, currentPhotoIndex]);
|
}, [openMediaViewer, userId, chatId, currentPhotoIndex, forceShowSelf]);
|
||||||
|
|
||||||
const selectPreviousMedia = useCallback(() => {
|
const selectPreviousMedia = useCallback(() => {
|
||||||
if (isFirst) {
|
if (isFirst) {
|
||||||
@ -174,7 +176,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
const isVerifiedIconShown = (user && user.isVerified) || (chat && chat.isVerified);
|
const isVerifiedIconShown = (user && user.isVerified) || (chat && chat.isVerified);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ProfileInfo" dir={lang.isRtl ? 'rtl' : undefined}>
|
<div className={buildClassName('ProfileInfo', forceShowSelf && 'self')} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
<div className="photo-wrapper">
|
<div className="photo-wrapper">
|
||||||
{renderPhotoTabs()}
|
{renderPhotoTabs()}
|
||||||
<Transition activeKey={currentPhotoIndex} name={slideAnimation} className="profile-slide-container">
|
<Transition activeKey={currentPhotoIndex} name={slideAnimation} className="profile-slide-container">
|
||||||
@ -218,15 +220,15 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, { userId, forceShowSelf }): StateProps => {
|
(global, { userId, forceShowSelf }): StateProps => {
|
||||||
const { lastSyncTime, serverTimeOffset } = global;
|
const { connectionState, serverTimeOffset } = global;
|
||||||
const user = selectUser(global, userId);
|
const user = selectUser(global, userId);
|
||||||
const chat = selectChat(global, userId);
|
const chat = selectChat(global, userId);
|
||||||
const isSavedMessages = !forceShowSelf && user && user.isSelf;
|
const isSavedMessages = !forceShowSelf && user && user.isSelf;
|
||||||
const { animationLevel } = global.settings.byKey;
|
const { animationLevel } = global.settings.byKey;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lastSyncTime, user, chat, isSavedMessages, animationLevel, serverTimeOffset,
|
connectionState, user, chat, isSavedMessages, animationLevel, serverTimeOffset,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullUser', 'openMediaViewer']),
|
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullUser', 'openMediaViewer']),
|
||||||
)(PrivateChatInfo));
|
)(ProfileInfo));
|
@ -7,7 +7,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
getChatAvatarHash, isDeletedUser, getUserColorKey, getChatTitle, isChatPrivate, getUserFullName,
|
getChatAvatarHash, isDeletedUser, getUserColorKey, getChatTitle, isChatPrivate, getUserFullName,
|
||||||
} from '../../modules/helpers';
|
} from '../../modules/helpers';
|
||||||
import renderText from '../common/helpers/renderText';
|
import renderText from './helpers/renderText';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { getFirstLetters } from '../../util/textFormat';
|
import { getFirstLetters } from '../../util/textFormat';
|
||||||
import useMedia from '../../hooks/useMedia';
|
import useMedia from '../../hooks/useMedia';
|
||||||
@ -59,11 +59,16 @@ const ProfilePhoto: FC<OwnProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const imageHash = getMediaHash();
|
const imageHash = getMediaHash();
|
||||||
const fullMediaData = useMedia(imageHash, false, ApiMediaFormat.BlobUrl, lastSyncTime);
|
const fullMediaData = useMedia(
|
||||||
|
imageHash,
|
||||||
|
false,
|
||||||
|
imageHash?.startsWith('avatar') ? ApiMediaFormat.DataUri : ApiMediaFormat.BlobUrl,
|
||||||
|
lastSyncTime,
|
||||||
|
);
|
||||||
const avatarThumbnailData = useMedia(
|
const avatarThumbnailData = useMedia(
|
||||||
!fullMediaData && isFirstPhoto ? getMediaHash('normal', true) : undefined,
|
!fullMediaData && isFirstPhoto ? getMediaHash('normal', true) : undefined,
|
||||||
false,
|
false,
|
||||||
ApiMediaFormat.BlobUrl,
|
ApiMediaFormat.DataUri,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
);
|
);
|
||||||
const thumbDataUri = useBlurSync(!fullMediaData && photo && photo.thumbnail && photo.thumbnail.dataUri);
|
const thumbDataUri = useBlurSync(!fullMediaData && photo && photo.thumbnail && photo.thumbnail.dataUri);
|
@ -19,6 +19,7 @@
|
|||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-left: 1.375rem;
|
margin-left: 1.375rem;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.SearchInput {
|
.SearchInput {
|
||||||
@ -33,4 +34,13 @@
|
|||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Button.smaller {
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
|
||||||
|
+ .DropdownMenu {
|
||||||
|
margin-left: .25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.left-header {
|
||||||
|
padding-right: .8125rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-main-header {
|
.settings-main-header {
|
||||||
@ -30,6 +34,7 @@
|
|||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
height: calc(100% - var(--header-height));
|
height: calc(100% - var(--header-height));
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-y: overlay;
|
||||||
|
|
||||||
&.infinite-scroll {
|
&.infinite-scroll {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -84,36 +89,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-main-menu {
|
.settings-main-menu {
|
||||||
padding: 0 0.5rem 1rem;
|
padding: 0 0.5rem .75rem;
|
||||||
}
|
|
||||||
|
|
||||||
.settings-current-user {
|
> .ChatExtra {
|
||||||
margin-bottom: 1.125rem;
|
padding: 0 .5rem .3125rem;
|
||||||
text-align: center;
|
margin: 0 -.5rem .625rem;
|
||||||
|
box-shadow: inset 0 -.0625rem 0 0 var(--color-background-secondary-accent);
|
||||||
|
border-bottom: .625rem solid var(--color-background-secondary);
|
||||||
|
|
||||||
.Avatar {
|
.ListItem.narrow {
|
||||||
margin: 0 auto 1.5rem;
|
margin-bottom: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
.VerifiedIcon {
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
margin-top: 0.1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.phone {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: #868e96;
|
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +334,7 @@ const Settings: FC<OwnProps> = ({
|
|||||||
currentScreen={currentScreen}
|
currentScreen={currentScreen}
|
||||||
onReset={handleReset}
|
onReset={handleReset}
|
||||||
onSaveFilter={handleSaveFilter}
|
onSaveFilter={handleSaveFilter}
|
||||||
|
onScreenSelect={onScreenSelect}
|
||||||
editedFolderId={foldersState.folderId}
|
editedFolderId={foldersState.folderId}
|
||||||
/>
|
/>
|
||||||
{renderCurrentSectionContent(isScreenActive, currentKey)}
|
{renderCurrentSectionContent(isScreenActive, currentKey)}
|
||||||
|
@ -20,6 +20,7 @@ type OwnProps = {
|
|||||||
editedFolderId?: number;
|
editedFolderId?: number;
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
onSaveFilter: () => void;
|
onSaveFilter: () => void;
|
||||||
|
onScreenSelect: (screen: SettingsScreens) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'signOut' | 'deleteChatFolder'>;
|
type DispatchProps = Pick<GlobalActions, 'signOut' | 'deleteChatFolder'>;
|
||||||
@ -31,6 +32,7 @@ const SettingsHeader: FC<OwnProps & DispatchProps> = ({
|
|||||||
onSaveFilter,
|
onSaveFilter,
|
||||||
signOut,
|
signOut,
|
||||||
deleteChatFolder,
|
deleteChatFolder,
|
||||||
|
onScreenSelect,
|
||||||
}) => {
|
}) => {
|
||||||
const [isSignOutDialogOpen, setIsSignOutDialogOpen] = useState(false);
|
const [isSignOutDialogOpen, setIsSignOutDialogOpen] = useState(false);
|
||||||
const [isDeleteFolderDialogOpen, setIsDeleteFolderDialogOpen] = useState(false);
|
const [isDeleteFolderDialogOpen, setIsDeleteFolderDialogOpen] = useState(false);
|
||||||
@ -205,6 +207,16 @@ const SettingsHeader: FC<OwnProps & DispatchProps> = ({
|
|||||||
<div className="settings-main-header">
|
<div className="settings-main-header">
|
||||||
<h3>{lang('SETTINGS')}</h3>
|
<h3>{lang('SETTINGS')}</h3>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
round
|
||||||
|
ripple={!IS_SINGLE_COLUMN_LAYOUT}
|
||||||
|
size="smaller"
|
||||||
|
color="translucent"
|
||||||
|
onClick={() => onScreenSelect(SettingsScreens.EditProfile)}
|
||||||
|
ariaLabel={lang('lng_settings_information')}
|
||||||
|
>
|
||||||
|
<i className="icon-edit" />
|
||||||
|
</Button>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
className="settings-more-menu"
|
className="settings-more-menu"
|
||||||
trigger={SettingsMenuButton}
|
trigger={SettingsMenuButton}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import React, { FC, memo } from '../../../lib/teact/teact';
|
import React, { FC, memo, useEffect } from '../../../lib/teact/teact';
|
||||||
import { withGlobal } from '../../../lib/teact/teactn';
|
import { withGlobal } from '../../../lib/teact/teactn';
|
||||||
|
|
||||||
|
import { GlobalActions } from '../../../global/types';
|
||||||
import { SettingsScreens } from '../../../types';
|
import { SettingsScreens } from '../../../types';
|
||||||
import { ApiUser } from '../../../api/types';
|
import { ApiUser } from '../../../api/types';
|
||||||
|
|
||||||
import { selectUser } from '../../../modules/selectors';
|
import { selectUser } from '../../../modules/selectors';
|
||||||
import { getUserFullName } from '../../../modules/helpers';
|
import { pick } from '../../../util/iteratees';
|
||||||
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
|
|
||||||
import renderText from '../../common/helpers/renderText';
|
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useHistoryBack from '../../../hooks/useHistoryBack';
|
import useHistoryBack from '../../../hooks/useHistoryBack';
|
||||||
|
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
import Avatar from '../../common/Avatar';
|
import ProfileInfo from '../../common/ProfileInfo';
|
||||||
|
import ChatExtra from '../../common/ChatExtra';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
@ -22,16 +22,27 @@ type OwnProps = {
|
|||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
currentUser?: ApiUser;
|
currentUser?: ApiUser;
|
||||||
|
lastSyncTime?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsMain: FC<OwnProps & StateProps> = ({
|
type DispatchProps = Pick<GlobalActions, 'loadProfilePhotos'>;
|
||||||
|
|
||||||
|
const SettingsMain: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||||
isActive,
|
isActive,
|
||||||
onScreenSelect,
|
onScreenSelect,
|
||||||
onReset,
|
onReset,
|
||||||
|
loadProfilePhotos,
|
||||||
currentUser,
|
currentUser,
|
||||||
|
lastSyncTime,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
const fullName = getUserFullName(currentUser);
|
const profileId = currentUser ? currentUser.id : undefined;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (profileId && lastSyncTime) {
|
||||||
|
loadProfilePhotos({ profileId });
|
||||||
|
}
|
||||||
|
}, [lastSyncTime, profileId, loadProfilePhotos]);
|
||||||
|
|
||||||
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.Main);
|
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.Main);
|
||||||
|
|
||||||
@ -39,24 +50,17 @@ const SettingsMain: FC<OwnProps & StateProps> = ({
|
|||||||
<div className="settings-content custom-scroll">
|
<div className="settings-content custom-scroll">
|
||||||
<div className="settings-main-menu">
|
<div className="settings-main-menu">
|
||||||
{currentUser && (
|
{currentUser && (
|
||||||
<div className="settings-current-user">
|
<ProfileInfo
|
||||||
<Avatar user={currentUser} size="jumbo" />
|
userId={currentUser.id}
|
||||||
<p className="name">{fullName && renderText(fullName)}</p>
|
forceShowSelf
|
||||||
<p className="phone">{formatPhoneNumberWithCode(currentUser.phoneNumber)}</p>
|
/>
|
||||||
</div>
|
)}
|
||||||
|
{currentUser && (
|
||||||
|
<ChatExtra
|
||||||
|
chatOrUserId={currentUser.id}
|
||||||
|
forceShowSelf
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<ListItem
|
|
||||||
icon="edit"
|
|
||||||
onClick={() => onScreenSelect(SettingsScreens.EditProfile)}
|
|
||||||
>
|
|
||||||
{lang('lng_settings_information')}
|
|
||||||
</ListItem>
|
|
||||||
<ListItem
|
|
||||||
icon="folder"
|
|
||||||
onClick={() => onScreenSelect(SettingsScreens.Folders)}
|
|
||||||
>
|
|
||||||
{lang('Filters')}
|
|
||||||
</ListItem>
|
|
||||||
<ListItem
|
<ListItem
|
||||||
icon="settings"
|
icon="settings"
|
||||||
onClick={() => onScreenSelect(SettingsScreens.General)}
|
onClick={() => onScreenSelect(SettingsScreens.General)}
|
||||||
@ -75,6 +79,12 @@ const SettingsMain: FC<OwnProps & StateProps> = ({
|
|||||||
>
|
>
|
||||||
{lang('PrivacySettings')}
|
{lang('PrivacySettings')}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
icon="folder"
|
||||||
|
onClick={() => onScreenSelect(SettingsScreens.Folders)}
|
||||||
|
>
|
||||||
|
{lang('Filters')}
|
||||||
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
icon="language"
|
icon="language"
|
||||||
onClick={() => onScreenSelect(SettingsScreens.Language)}
|
onClick={() => onScreenSelect(SettingsScreens.Language)}
|
||||||
@ -88,10 +98,12 @@ const SettingsMain: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global): StateProps => {
|
(global): StateProps => {
|
||||||
const { currentUserId } = global;
|
const { currentUserId, lastSyncTime } = global;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentUser: currentUserId ? selectUser(global, currentUserId) : undefined,
|
currentUser: currentUserId ? selectUser(global, currentUserId) : undefined,
|
||||||
|
lastSyncTime,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
(setGlobal, actions): DispatchProps => pick(actions, ['loadProfilePhotos']),
|
||||||
)(SettingsMain));
|
)(SettingsMain));
|
||||||
|
@ -143,7 +143,7 @@ export function animateClosing(origin: MediaViewerOrigin, bestImageData: string,
|
|||||||
|
|
||||||
const existingGhost = document.getElementsByClassName('ghost')[0] as HTMLDivElement;
|
const existingGhost = document.getElementsByClassName('ghost')[0] as HTMLDivElement;
|
||||||
|
|
||||||
const ghost = existingGhost || createGhost(bestImageData || toImage, origin === MediaViewerOrigin.ProfileAvatar);
|
const ghost = existingGhost || createGhost(bestImageData || toImage, origin);
|
||||||
if (!existingGhost) {
|
if (!existingGhost) {
|
||||||
applyStyles(ghost, {
|
applyStyles(ghost, {
|
||||||
top: `${toTop}px`,
|
top: `${toTop}px`,
|
||||||
@ -203,7 +203,7 @@ export function animateClosing(origin: MediaViewerOrigin, bestImageData: string,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGhost(source: string | HTMLImageElement | HTMLVideoElement, shouldAppendProfileInfo = false) {
|
function createGhost(source: string | HTMLImageElement | HTMLVideoElement, origin?: MediaViewerOrigin) {
|
||||||
const ghost = document.createElement('div');
|
const ghost = document.createElement('div');
|
||||||
ghost.classList.add('ghost');
|
ghost.classList.add('ghost');
|
||||||
|
|
||||||
@ -219,9 +219,16 @@ function createGhost(source: string | HTMLImageElement | HTMLVideoElement, shoul
|
|||||||
|
|
||||||
ghost.appendChild(img);
|
ghost.appendChild(img);
|
||||||
|
|
||||||
if (shouldAppendProfileInfo) {
|
if (origin === MediaViewerOrigin.ProfileAvatar || origin === MediaViewerOrigin.SettingsAvatar) {
|
||||||
ghost.classList.add('ProfileInfo');
|
ghost.classList.add('ProfileInfo');
|
||||||
const profileInfo = document.querySelector('#RightColumn .ProfileInfo .info');
|
if (origin === MediaViewerOrigin.SettingsAvatar) {
|
||||||
|
ghost.classList.add('self');
|
||||||
|
}
|
||||||
|
const profileInfo = document.querySelector(
|
||||||
|
origin === MediaViewerOrigin.ProfileAvatar
|
||||||
|
? '#RightColumn .ProfileInfo .info'
|
||||||
|
: '#Settings .ProfileInfo .info',
|
||||||
|
);
|
||||||
if (profileInfo) {
|
if (profileInfo) {
|
||||||
ghost.appendChild(profileInfo.cloneNode(true));
|
ghost.appendChild(profileInfo.cloneNode(true));
|
||||||
}
|
}
|
||||||
@ -314,6 +321,11 @@ function getNodes(origin: MediaViewerOrigin, message?: ApiMessage) {
|
|||||||
mediaSelector = 'img.avatar-media';
|
mediaSelector = 'img.avatar-media';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MediaViewerOrigin.SettingsAvatar:
|
||||||
|
containerSelector = '#Settings .ProfileInfo .active .ProfilePhoto';
|
||||||
|
mediaSelector = 'img.avatar-media';
|
||||||
|
break;
|
||||||
|
|
||||||
case MediaViewerOrigin.ProfileAvatar:
|
case MediaViewerOrigin.ProfileAvatar:
|
||||||
containerSelector = '#RightColumn .ProfileInfo .active .ProfilePhoto';
|
containerSelector = '#RightColumn .ProfileInfo .active .ProfilePhoto';
|
||||||
mediaSelector = 'img.avatar-media';
|
mediaSelector = 'img.avatar-media';
|
||||||
@ -345,6 +357,7 @@ function applyShape(ghost: HTMLDivElement, origin: MediaViewerOrigin) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MediaViewerOrigin.SharedMedia:
|
case MediaViewerOrigin.SharedMedia:
|
||||||
|
case MediaViewerOrigin.SettingsAvatar:
|
||||||
case MediaViewerOrigin.ProfileAvatar:
|
case MediaViewerOrigin.ProfileAvatar:
|
||||||
case MediaViewerOrigin.SearchResult:
|
case MediaViewerOrigin.SearchResult:
|
||||||
(ghost.firstChild as HTMLElement).style.objectFit = 'cover';
|
(ghost.firstChild as HTMLElement).style.objectFit = 'cover';
|
||||||
|
@ -46,10 +46,10 @@ import TabList from '../ui/TabList';
|
|||||||
import Spinner from '../ui/Spinner';
|
import Spinner from '../ui/Spinner';
|
||||||
import ListItem from '../ui/ListItem';
|
import ListItem from '../ui/ListItem';
|
||||||
import PrivateChatInfo from '../common/PrivateChatInfo';
|
import PrivateChatInfo from '../common/PrivateChatInfo';
|
||||||
import ProfileInfo from './ProfileInfo';
|
import ProfileInfo from '../common/ProfileInfo';
|
||||||
import Document from '../common/Document';
|
import Document from '../common/Document';
|
||||||
import Audio from '../common/Audio';
|
import Audio from '../common/Audio';
|
||||||
import ChatExtra from './ChatExtra';
|
import ChatExtra from '../common/ChatExtra';
|
||||||
import Media from '../common/Media';
|
import Media from '../common/Media';
|
||||||
import WebLink from '../common/WebLink';
|
import WebLink from '../common/WebLink';
|
||||||
import NothingFound from '../common/NothingFound';
|
import NothingFound from '../common/NothingFound';
|
||||||
@ -405,11 +405,8 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
function renderProfileInfo(chatId: number, resolvedUserId?: number) {
|
function renderProfileInfo(chatId: number, resolvedUserId?: number) {
|
||||||
return (
|
return (
|
||||||
<div className="profile-info">
|
<div className="profile-info">
|
||||||
<ProfileInfo
|
<ProfileInfo userId={resolvedUserId || chatId} />
|
||||||
userId={resolvedUserId || chatId}
|
<ChatExtra chatOrUserId={resolvedUserId || chatId} />
|
||||||
forceShowSelf={resolvedUserId !== chatId}
|
|
||||||
/>
|
|
||||||
<ChatExtra chatOrUserId={resolvedUserId || chatId} forceShowSelf={resolvedUserId !== chatId} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -230,6 +230,7 @@ export enum MediaViewerOrigin {
|
|||||||
ScheduledInline,
|
ScheduledInline,
|
||||||
SharedMedia,
|
SharedMedia,
|
||||||
ProfileAvatar,
|
ProfileAvatar,
|
||||||
|
SettingsAvatar,
|
||||||
MiddleHeaderAvatar,
|
MiddleHeaderAvatar,
|
||||||
Album,
|
Album,
|
||||||
ScheduledAlbum,
|
ScheduledAlbum,
|
||||||
|
Loading…
Reference in New Issue
Block a user