Media Viewer: Support selecting main photo for profile and chats (#2162)
This commit is contained in:
parent
be044c2aa1
commit
f5b8b09f37
@ -12,7 +12,7 @@ import type {
|
||||
ApiChatBannedRights,
|
||||
ApiChatAdminRights,
|
||||
ApiGroupCall,
|
||||
ApiUserStatus,
|
||||
ApiUserStatus, ApiPhoto,
|
||||
} from '../../types';
|
||||
|
||||
import {
|
||||
@ -41,7 +41,7 @@ import {
|
||||
isMessageWithMedia,
|
||||
buildChatBannedRights,
|
||||
buildChatAdminRights,
|
||||
buildInputChatReactions,
|
||||
buildInputChatReactions, buildInputPhoto,
|
||||
} from '../gramjsBuilders';
|
||||
import { addEntitiesWithPhotosToLocalDb, addMessageToLocalDb, addPhotoToLocalDb } from '../helpers';
|
||||
import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
|
||||
@ -693,24 +693,33 @@ export async function createGroupChat({
|
||||
export async function editChatPhoto({
|
||||
chatId, accessHash, photo,
|
||||
}: {
|
||||
chatId: string; accessHash?: string; photo: File;
|
||||
chatId: string; accessHash?: string; photo?: File | ApiPhoto;
|
||||
}) {
|
||||
const uploadedPhoto = await uploadFile(photo);
|
||||
const inputEntity = buildInputEntity(chatId, accessHash);
|
||||
|
||||
let inputPhoto: GramJs.TypeInputChatPhoto;
|
||||
if (photo instanceof File) {
|
||||
const uploadedPhoto = await uploadFile(photo);
|
||||
inputPhoto = new GramJs.InputChatUploadedPhoto({
|
||||
file: uploadedPhoto,
|
||||
});
|
||||
} else if (photo) {
|
||||
const photoId = buildInputPhoto(photo);
|
||||
if (!photoId) return false;
|
||||
inputPhoto = new GramJs.InputChatPhoto({
|
||||
id: photoId,
|
||||
});
|
||||
} else {
|
||||
inputPhoto = new GramJs.InputChatPhotoEmpty();
|
||||
}
|
||||
return invokeRequest(
|
||||
inputEntity instanceof GramJs.InputChannel
|
||||
? new GramJs.channels.EditPhoto({
|
||||
channel: inputEntity as GramJs.InputChannel,
|
||||
photo: new GramJs.InputChatUploadedPhoto({
|
||||
file: uploadedPhoto,
|
||||
}),
|
||||
photo: inputPhoto,
|
||||
})
|
||||
: new GramJs.messages.EditChatPhoto({
|
||||
chatId: inputEntity as BigInt.BigInteger,
|
||||
photo: new GramJs.InputChatUploadedPhoto({
|
||||
file: uploadedPhoto,
|
||||
}),
|
||||
photo: inputPhoto,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
@ -54,7 +54,7 @@ export {
|
||||
|
||||
export {
|
||||
updateProfile, checkUsername, updateUsername, fetchBlockedContacts, blockContact, unblockContact,
|
||||
updateProfilePhoto, uploadProfilePhoto, deleteProfilePhoto, fetchWallpapers, uploadWallpaper,
|
||||
updateProfilePhoto, uploadProfilePhoto, deleteProfilePhotos, fetchWallpapers, uploadWallpaper,
|
||||
fetchAuthorizations, terminateAuthorization, terminateAllAuthorizations,
|
||||
fetchWebAuthorizations, terminateWebAuthorization, terminateAllWebAuthorizations,
|
||||
fetchNotificationExceptions, fetchNotificationSettings, updateContactSignUpNotification, updateNotificationSettings,
|
||||
|
||||
@ -21,6 +21,7 @@ import {
|
||||
buildPrivacyRules,
|
||||
} from '../apiBuilders/misc';
|
||||
|
||||
import { buildApiPhoto } from '../apiBuilders/common';
|
||||
import { buildApiUser } from '../apiBuilders/users';
|
||||
import { buildApiChatFromPreview } from '../apiBuilders/chats';
|
||||
import { getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
|
||||
@ -32,7 +33,7 @@ import {
|
||||
import { getClient, invokeRequest, uploadFile } from './client';
|
||||
import { buildCollectionByKey } from '../../../util/iteratees';
|
||||
import { getServerTime } from '../../../util/serverTime';
|
||||
import { addEntitiesWithPhotosToLocalDb } from '../helpers';
|
||||
import { addEntitiesWithPhotosToLocalDb, addPhotoToLocalDb } from '../helpers';
|
||||
import localDb from '../localDb';
|
||||
|
||||
const MAX_INT_32 = 2 ** 31 - 1;
|
||||
@ -67,26 +68,32 @@ export function updateUsername(username: string) {
|
||||
return invokeRequest(new GramJs.account.UpdateUsername({ username }), true);
|
||||
}
|
||||
|
||||
export async function updateProfilePhoto(file: File) {
|
||||
export async function updateProfilePhoto(photo?: ApiPhoto) {
|
||||
const photoId = photo ? buildInputPhoto(photo) : new GramJs.InputPhotoEmpty();
|
||||
const result = await invokeRequest(new GramJs.photos.UpdateProfilePhoto({
|
||||
id: photoId,
|
||||
}));
|
||||
if (result?.photo instanceof GramJs.Photo) {
|
||||
addPhotoToLocalDb(result.photo);
|
||||
return buildApiPhoto(result.photo);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export async function uploadProfilePhoto(file: File) {
|
||||
const inputFile = await uploadFile(file);
|
||||
return invokeRequest(new GramJs.photos.UploadProfilePhoto({
|
||||
file: inputFile,
|
||||
}), true);
|
||||
}
|
||||
|
||||
export async function uploadProfilePhoto(file: File) {
|
||||
const inputFile = await uploadFile(file);
|
||||
await invokeRequest(new GramJs.photos.UploadProfilePhoto({
|
||||
file: inputFile,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function deleteProfilePhoto(photo: ApiPhoto) {
|
||||
const photoId = buildInputPhoto(photo);
|
||||
if (!photoId) return false;
|
||||
const isDeleted = await invokeRequest(new GramJs.photos.DeletePhotos({ id: [photoId] }), true);
|
||||
export async function deleteProfilePhotos(photos: ApiPhoto[]) {
|
||||
const photoIds = photos.map(buildInputPhoto).filter(Boolean);
|
||||
const isDeleted = await invokeRequest(new GramJs.photos.DeletePhotos({ id: photoIds }), true);
|
||||
if (isDeleted) {
|
||||
delete localDb.photos[photo.id];
|
||||
photos.forEach((photo) => {
|
||||
delete localDb.photos[photo.id];
|
||||
});
|
||||
}
|
||||
return isDeleted;
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import useLang from '../../hooks/useLang';
|
||||
|
||||
import Modal from '../ui/Modal';
|
||||
import Button from '../ui/Button';
|
||||
import { isUserId } from '../../global/helpers';
|
||||
|
||||
export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
@ -25,13 +26,21 @@ const DeleteProfilePhotoModal: FC<OwnProps> = ({
|
||||
}) => {
|
||||
const {
|
||||
deleteProfilePhoto,
|
||||
deleteChatPhoto,
|
||||
} = getActions();
|
||||
|
||||
const handleDeletePhoto = useCallback(() => {
|
||||
onConfirm?.();
|
||||
deleteProfilePhoto({ photo, profileId });
|
||||
if (isUserId(profileId)) {
|
||||
deleteProfilePhoto({ photo });
|
||||
} else {
|
||||
deleteChatPhoto({
|
||||
photo,
|
||||
chatId: profileId,
|
||||
});
|
||||
}
|
||||
onClose();
|
||||
}, [onConfirm, deleteProfilePhoto, photo, profileId, onClose]);
|
||||
}, [onConfirm, profileId, onClose, deleteProfilePhoto, photo, deleteChatPhoto]);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
|
||||
@ -179,7 +179,9 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
function renderPhoto(isActive?: boolean) {
|
||||
const photo = !isSavedMessages && photos.length > 0 ? photos[currentPhotoIndex] : undefined;
|
||||
const photo = !isSavedMessages && photos.length > 0
|
||||
? photos[currentPhotoIndex]
|
||||
: undefined;
|
||||
return (
|
||||
<ProfilePhoto
|
||||
key={currentPhotoIndex}
|
||||
|
||||
@ -11,7 +11,7 @@ import { MediaViewerOrigin } from '../../types';
|
||||
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
import {
|
||||
getChatMediaMessageIds,
|
||||
getChatMediaMessageIds, isChatAdmin,
|
||||
} from '../../global/helpers';
|
||||
import {
|
||||
selectChat,
|
||||
@ -59,7 +59,7 @@ type StateProps = {
|
||||
mediaId?: number;
|
||||
senderId?: string;
|
||||
isChatWithSelf?: boolean;
|
||||
canDeleteMedia?: boolean;
|
||||
canUpdateMedia?: boolean;
|
||||
origin?: MediaViewerOrigin;
|
||||
avatarOwner?: ApiChat | ApiUser;
|
||||
message?: ApiMessage;
|
||||
@ -78,7 +78,7 @@ const MediaViewer: FC<StateProps> = ({
|
||||
mediaId,
|
||||
senderId,
|
||||
isChatWithSelf,
|
||||
canDeleteMedia,
|
||||
canUpdateMedia,
|
||||
origin,
|
||||
avatarOwner,
|
||||
message,
|
||||
@ -336,11 +336,12 @@ const MediaViewer: FC<StateProps> = ({
|
||||
mediaData={bestData}
|
||||
isVideo={isVideo}
|
||||
message={message}
|
||||
canDeleteAvatar={canDeleteMedia && !!avatarPhoto}
|
||||
canUpdateMedia={canUpdateMedia}
|
||||
avatarPhoto={avatarPhoto}
|
||||
avatarOwnerId={avatarOwner?.id}
|
||||
avatarOwner={avatarOwner}
|
||||
fileName={fileName}
|
||||
canReport={canReport}
|
||||
selectMedia={selectMedia}
|
||||
onBeforeDelete={handleBeforeDelete}
|
||||
onReport={openReportModal}
|
||||
onCloseMediaViewer={handleClose}
|
||||
@ -422,10 +423,13 @@ export default memo(withGlobal(
|
||||
if (avatarOwnerId) {
|
||||
const user = selectUser(global, avatarOwnerId);
|
||||
const chat = selectChat(global, avatarOwnerId);
|
||||
let canDeleteMedia = false;
|
||||
if (user) canDeleteMedia = avatarOwnerId === currentUserId;
|
||||
// TODO Support deleting chat photos
|
||||
// if (chat) canDeleteMedia = isChatAdmin(chat);
|
||||
let canUpdateMedia = false;
|
||||
if (user) {
|
||||
canUpdateMedia = avatarOwnerId === currentUserId;
|
||||
} else if (chat) {
|
||||
canUpdateMedia = isChatAdmin(chat);
|
||||
}
|
||||
|
||||
isChatWithSelf = selectIsChatWithSelf(global, avatarOwnerId);
|
||||
|
||||
return {
|
||||
@ -433,7 +437,7 @@ export default memo(withGlobal(
|
||||
senderId: avatarOwnerId,
|
||||
avatarOwner: user || chat,
|
||||
isChatWithSelf,
|
||||
canDeleteMedia,
|
||||
canUpdateMedia,
|
||||
animationLevel,
|
||||
origin,
|
||||
shouldSkipHistoryAnimations,
|
||||
|
||||
@ -7,7 +7,7 @@ import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type {
|
||||
ApiMessage, ApiPhoto,
|
||||
ApiMessage, ApiPhoto, ApiChat, ApiUser,
|
||||
} from '../../api/types';
|
||||
import type { MessageListType } from '../../global/types';
|
||||
import type { MenuItemProps } from '../ui/MenuItem';
|
||||
@ -20,7 +20,7 @@ import {
|
||||
selectIsChatProtected,
|
||||
} from '../../global/selectors';
|
||||
import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
|
||||
import { getMessageMediaFormat, getMessageMediaHash } from '../../global/helpers';
|
||||
import { getMessageMediaFormat, getMessageMediaHash, isUserId } from '../../global/helpers';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
|
||||
@ -40,7 +40,9 @@ type StateProps = {
|
||||
isProtected?: boolean;
|
||||
isChatProtected?: boolean;
|
||||
canDelete?: boolean;
|
||||
canUpdate?: boolean;
|
||||
messageListType?: MessageListType;
|
||||
avatarOwnerId?: string;
|
||||
};
|
||||
|
||||
type OwnProps = {
|
||||
@ -48,11 +50,13 @@ type OwnProps = {
|
||||
isVideo: boolean;
|
||||
zoomLevelChange: number;
|
||||
message?: ApiMessage;
|
||||
canDeleteAvatar?: boolean;
|
||||
canUpdateMedia?: boolean;
|
||||
isSingleMedia?: boolean;
|
||||
avatarPhoto?: ApiPhoto;
|
||||
avatarOwnerId?: string;
|
||||
avatarOwner?: ApiChat | ApiUser;
|
||||
fileName?: string;
|
||||
canReport?: boolean;
|
||||
selectMedia: (mediaId?: number) => void;
|
||||
onReport: NoneToVoidFunction;
|
||||
onBeforeDelete: NoneToVoidFunction;
|
||||
onCloseMediaViewer: NoneToVoidFunction;
|
||||
@ -73,7 +77,9 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
canReport,
|
||||
zoomLevelChange,
|
||||
canDelete,
|
||||
canUpdate,
|
||||
messageListType,
|
||||
selectMedia,
|
||||
onReport,
|
||||
onCloseMediaViewer,
|
||||
onBeforeDelete,
|
||||
@ -85,6 +91,8 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
const {
|
||||
downloadMessageMedia,
|
||||
cancelMessageMediaDownload,
|
||||
updateProfilePhoto,
|
||||
updateChatPhoto,
|
||||
} = getActions();
|
||||
|
||||
const { loadProgress: downloadProgress } = useMediaWithLoadProgress(
|
||||
@ -111,6 +119,16 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
setZoomLevelChange(change + 1);
|
||||
}, [setZoomLevelChange, zoomLevelChange]);
|
||||
|
||||
const handleUpdate = useCallback(() => {
|
||||
if (!avatarPhoto || !avatarOwnerId) return;
|
||||
if (isUserId(avatarOwnerId)) {
|
||||
updateProfilePhoto({ photo: avatarPhoto });
|
||||
} else {
|
||||
updateChatPhoto({ chatId: avatarOwnerId, photo: avatarPhoto });
|
||||
}
|
||||
selectMedia(0);
|
||||
}, [avatarPhoto, avatarOwnerId, selectMedia, updateProfilePhoto, updateChatPhoto]);
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const MenuButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {
|
||||
@ -217,6 +235,14 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (canUpdate) {
|
||||
menuItems.push({
|
||||
icon: 'copy-media',
|
||||
onClick: handleUpdate,
|
||||
children: lang('ProfilePhoto.SetMainPhoto'),
|
||||
});
|
||||
}
|
||||
|
||||
if (canDelete) {
|
||||
menuItems.push({
|
||||
icon: 'delete',
|
||||
@ -298,6 +324,17 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
<i className="icon-flag" />
|
||||
</Button>
|
||||
)}
|
||||
{canUpdate && (
|
||||
<Button
|
||||
round
|
||||
size="smaller"
|
||||
color="translucent-white"
|
||||
ariaLabel={lang('ProfilePhoto.SetMainPhoto')}
|
||||
onClick={handleUpdate}
|
||||
>
|
||||
<i className="icon-copy-media" />
|
||||
</Button>
|
||||
)}
|
||||
{canDelete && (
|
||||
<Button
|
||||
round
|
||||
@ -324,7 +361,9 @@ const MediaViewerActions: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { message, canDeleteAvatar }): StateProps => {
|
||||
(global, {
|
||||
message, canUpdateMedia, avatarPhoto, avatarOwner,
|
||||
}): StateProps => {
|
||||
const currentMessageList = selectCurrentMessageList(global);
|
||||
const { threadId } = selectCurrentMessageList(global) || {};
|
||||
const isDownloading = message ? selectIsDownloading(global, message) : false;
|
||||
@ -332,7 +371,10 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isChatProtected = message && selectIsChatProtected(global, message?.chatId);
|
||||
const { canDelete: canDeleteMessage } = (threadId
|
||||
&& message && selectAllowedMessageActions(global, message, threadId)) || {};
|
||||
const isCurrentAvatar = avatarPhoto && (avatarPhoto.id === avatarOwner?.avatarHash);
|
||||
const canDeleteAvatar = canUpdateMedia && !!avatarPhoto;
|
||||
const canDelete = canDeleteMessage || canDeleteAvatar;
|
||||
const canUpdate = canUpdateMedia && !!avatarPhoto && !isCurrentAvatar;
|
||||
const messageListType = currentMessageList?.type;
|
||||
|
||||
return {
|
||||
@ -340,7 +382,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
isProtected,
|
||||
isChatProtected,
|
||||
canDelete,
|
||||
canUpdate,
|
||||
messageListType,
|
||||
avatarOwnerId: avatarOwner?.id,
|
||||
};
|
||||
},
|
||||
)(MediaViewerActions));
|
||||
|
||||
@ -923,6 +923,56 @@ addActionHandler('updateChat', async (global, actions, payload) => {
|
||||
setGlobal(updateManagementProgress(getGlobal(), ManagementProgress.Complete));
|
||||
});
|
||||
|
||||
addActionHandler('updateChatPhoto', async (global, actions, payload) => {
|
||||
const { photo, chatId } = payload;
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) return;
|
||||
setGlobal(updateChat(global, chatId, {
|
||||
avatarHash: undefined,
|
||||
fullInfo: {
|
||||
...chat.fullInfo,
|
||||
profilePhoto: undefined,
|
||||
},
|
||||
}));
|
||||
// This method creates a new entry in photos array
|
||||
await callApi('editChatPhoto', {
|
||||
chatId,
|
||||
accessHash: chat.accessHash,
|
||||
photo,
|
||||
});
|
||||
// Explicitly delete the old photo reference
|
||||
await callApi('deleteProfilePhotos', [photo]);
|
||||
actions.loadFullChat({ chatId });
|
||||
actions.loadProfilePhotos({ profileId: chatId });
|
||||
});
|
||||
|
||||
addActionHandler('deleteChatPhoto', async (global, actions, payload) => {
|
||||
const { photo, chatId } = payload;
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) return;
|
||||
// Select next photo to set as avatar
|
||||
const nextPhoto = chat.photos?.[1];
|
||||
setGlobal(updateChat(global, chatId, {
|
||||
avatarHash: undefined,
|
||||
fullInfo: {
|
||||
...chat.fullInfo,
|
||||
profilePhoto: undefined,
|
||||
},
|
||||
}));
|
||||
// Set next photo as avatar
|
||||
await callApi('editChatPhoto', {
|
||||
chatId,
|
||||
accessHash: chat.accessHash,
|
||||
photo: nextPhoto,
|
||||
});
|
||||
// Delete references to the old photos
|
||||
const photosToDelete = [photo, nextPhoto].filter(Boolean);
|
||||
const result = await callApi('deleteProfilePhotos', photosToDelete);
|
||||
if (!result) return;
|
||||
actions.loadFullChat({ chatId });
|
||||
actions.loadProfilePhotos({ profileId: chatId });
|
||||
});
|
||||
|
||||
addActionHandler('toggleSignatures', (global, actions, payload) => {
|
||||
const { chatId, isEnabled } = payload!;
|
||||
const chat = selectChat(global, chatId);
|
||||
|
||||
@ -14,7 +14,7 @@ import { callApi } from '../../../api/gramjs';
|
||||
import { buildCollectionByKey } from '../../../util/iteratees';
|
||||
import { subscribe, unsubscribe } from '../../../util/notifications';
|
||||
import { setTimeFormat } from '../../../util/langProvider';
|
||||
import { selectUser } from '../../selectors';
|
||||
import { selectUser, selectChat } from '../../selectors';
|
||||
import {
|
||||
addUsers, addBlockedContact, updateChats, updateUser, removeBlockedContact, replaceSettings, updateNotifySettings,
|
||||
addNotifyExceptions,
|
||||
@ -39,7 +39,7 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
|
||||
});
|
||||
|
||||
if (photo) {
|
||||
const result = await callApi('updateProfilePhoto', photo);
|
||||
const result = await callApi('uploadProfilePhoto', photo);
|
||||
if (result) {
|
||||
actions.loadProfilePhotos({ profileId: currentUserId });
|
||||
}
|
||||
@ -83,16 +83,52 @@ addActionHandler('updateProfile', async (global, actions, payload) => {
|
||||
});
|
||||
});
|
||||
|
||||
addActionHandler('deleteProfilePhoto', async (global, actions, payload) => {
|
||||
const { photo, profileId } = payload;
|
||||
const result = await callApi('deleteProfilePhoto', photo);
|
||||
if (!result) return;
|
||||
if (isUserId(profileId)) {
|
||||
actions.loadFullUser({ userId: profileId });
|
||||
} else {
|
||||
actions.loadFullChat({ chatId: profileId });
|
||||
addActionHandler('updateProfilePhoto', async (global, actions, payload) => {
|
||||
const { photo } = payload;
|
||||
const { currentUserId } = global;
|
||||
if (!currentUserId) return;
|
||||
const currentUser = selectChat(global, currentUserId);
|
||||
if (!currentUser) return;
|
||||
setGlobal(updateUser(global, currentUserId, {
|
||||
avatarHash: undefined,
|
||||
fullInfo: {
|
||||
...currentUser.fullInfo,
|
||||
profilePhoto: undefined,
|
||||
},
|
||||
}));
|
||||
const newPhoto = await callApi('updateProfilePhoto', photo);
|
||||
if (newPhoto) {
|
||||
setGlobal(updateUser(getGlobal(), currentUserId, {
|
||||
avatarHash: newPhoto.id,
|
||||
fullInfo: {
|
||||
...currentUser.fullInfo,
|
||||
profilePhoto: newPhoto,
|
||||
},
|
||||
}));
|
||||
actions.loadFullUser({ userId: currentUserId });
|
||||
actions.loadProfilePhotos({ profileId: currentUserId });
|
||||
}
|
||||
actions.loadProfilePhotos({ profileId });
|
||||
});
|
||||
|
||||
addActionHandler('deleteProfilePhoto', async (global, actions, payload) => {
|
||||
const { photo } = payload;
|
||||
const { currentUserId } = global;
|
||||
if (!currentUserId) return;
|
||||
const currentUser = selectChat(global, currentUserId);
|
||||
if (!currentUser) return;
|
||||
if (currentUser.avatarHash === photo.id) {
|
||||
setGlobal(updateUser(global, currentUserId, {
|
||||
avatarHash: undefined,
|
||||
fullInfo: {
|
||||
...currentUser.fullInfo,
|
||||
profilePhoto: undefined,
|
||||
},
|
||||
}));
|
||||
}
|
||||
const result = await callApi('deleteProfilePhotos', [photo]);
|
||||
if (!result) return;
|
||||
actions.loadFullUser({ userId: currentUserId });
|
||||
actions.loadProfilePhotos({ profileId: currentUserId });
|
||||
});
|
||||
|
||||
addActionHandler('checkUsername', async (global, actions, payload) => {
|
||||
|
||||
@ -251,11 +251,15 @@ addActionHandler('loadProfilePhotos', async (global, actions, payload) => {
|
||||
|
||||
global = getGlobal();
|
||||
|
||||
const userOrChat = user || chat;
|
||||
const { photos } = result;
|
||||
photos.sort((a) => (a.id === userOrChat?.avatarHash ? -1 : 1));
|
||||
|
||||
if (isPrivate) {
|
||||
global = updateUser(global, profileId, { photos: result.photos });
|
||||
global = updateUser(global, profileId, { photos });
|
||||
} else {
|
||||
global = addUsers(global, buildCollectionByKey(result.users!, 'id'));
|
||||
global = updateChat(global, profileId, { photos: result.photos });
|
||||
global = updateChat(global, profileId, { photos });
|
||||
}
|
||||
|
||||
setGlobal(global);
|
||||
|
||||
@ -741,6 +741,14 @@ export interface ActionPayloads {
|
||||
chatId: string;
|
||||
force?: boolean;
|
||||
};
|
||||
updateChatPhoto: {
|
||||
chatId: string;
|
||||
photo: ApiPhoto;
|
||||
};
|
||||
deleteChatPhoto: {
|
||||
chatId: string;
|
||||
photo: ApiPhoto;
|
||||
};
|
||||
openChatWithDraft: {
|
||||
chatId?: string;
|
||||
text: string;
|
||||
@ -884,7 +892,9 @@ export interface ActionPayloads {
|
||||
profileId: string;
|
||||
};
|
||||
deleteProfilePhoto: {
|
||||
profileId: string;
|
||||
photo: ApiPhoto;
|
||||
};
|
||||
updateProfilePhoto: {
|
||||
photo: ApiPhoto;
|
||||
};
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
import { default as Api } from '../tl/api';
|
||||
import { SecurityError } from '../errors';
|
||||
// eslint-disable-next-line import/no-named-default
|
||||
import { default as MTProtoPlainSender } from './MTProtoPlainSender';
|
||||
import type { default as MTProtoPlainSender } from './MTProtoPlainSender';
|
||||
import { SERVER_KEYS } from '../crypto/RSA';
|
||||
|
||||
const bigInt = require('big-integer');
|
||||
|
||||
@ -1232,6 +1232,7 @@ messages.getExtendedMedia#84f80814 peer:InputPeer id:Vector<int> = Updates;
|
||||
updates.getState#edd4882a = updates.State;
|
||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||
updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;
|
||||
photos.updateProfilePhoto#72d4742c id:InputPhoto = photos.Photo;
|
||||
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
|
||||
photos.deletePhotos#87cf7f2f id:Vector<InputPhoto> = Vector<long>;
|
||||
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;
|
||||
|
||||
@ -163,6 +163,7 @@
|
||||
"updates.getDifference",
|
||||
"updates.getChannelDifference",
|
||||
"photos.uploadProfilePhoto",
|
||||
"photos.updateProfilePhoto",
|
||||
"photos.getUserPhotos",
|
||||
"photos.deletePhotos",
|
||||
"upload.saveFilePart",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user