From 330202960cf0d6b4323bc58fa90da7c0a2ba09e9 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:29:45 -0800 Subject: [PATCH] Fix dropped avatar on PNP settings update --- ts/services/usernameIntegrity.ts | 17 +------------- ts/services/writeProfile.ts | 39 +++++++++++++++++++++++++++++--- ts/state/ducks/conversations.ts | 6 +++-- ts/util/createIPCEvents.ts | 3 +-- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/ts/services/usernameIntegrity.ts b/ts/services/usernameIntegrity.ts index 8d3bc205e..b6bb21d10 100644 --- a/ts/services/usernameIntegrity.ts +++ b/ts/services/usernameIntegrity.ts @@ -11,9 +11,7 @@ import { explodePromise } from '../util/explodePromise'; import { BackOff, FIBONACCI_TIMEOUTS } from '../util/BackOff'; import { checkForUsername } from '../util/lookupConversationWithoutServiceId'; import { storageJobQueue } from '../util/JobQueue'; -import { getAbsoluteProfileAvatarPath } from '../util/avatarUtils'; import { getProfile } from '../util/getProfile'; -import { imagePathToBytes } from '../util/imagePathToBytes'; import { isSharingPhoneNumberWithEverybody } from '../util/phoneNumberSharingMode'; import * as log from '../logging/log'; import { resolveUsernameByLink } from './username'; @@ -169,21 +167,8 @@ class UsernameIntegrityService { 'updating profile' ); - const profileAvatarPath = getAbsoluteProfileAvatarPath(me.attributes); - - let avatarBuffer: Uint8Array | undefined; - if (profileAvatarPath) { - try { - avatarBuffer = await imagePathToBytes(profileAvatarPath); - } catch (error) { - log.error('usernameIntegrity: local avatar not found, aborting'); - return; - } - } - await writeProfile(getConversation(me), { - oldAvatar: avatarBuffer, - newAvatar: avatarBuffer, + keepAvatar: true, }); log.warn('usernameIntegrity: updated profile'); diff --git a/ts/services/writeProfile.ts b/ts/services/writeProfile.ts index 82f0347ba..73b1b5356 100644 --- a/ts/services/writeProfile.ts +++ b/ts/services/writeProfile.ts @@ -11,12 +11,24 @@ import { getProfile } from '../util/getProfile'; import { singleProtoJobQueue } from '../jobs/singleProtoJobQueue'; import { strictAssert } from '../util/assert'; import { isWhitespace } from '../util/whitespaceStringUtil'; +import { imagePathToBytes } from '../util/imagePathToBytes'; +import { getAbsoluteProfileAvatarPath } from '../util/avatarUtils'; import type { AvatarUpdateType } from '../types/Avatar'; import MessageSender from '../textsecure/SendMessage'; +export type WriteProfileOptionsType = Readonly< + | { + keepAvatar: true; + } + | { + keepAvatar?: false; + avatarUpdate: AvatarUpdateType; + } +>; + export async function writeProfile( conversation: ConversationType, - avatar: AvatarUpdateType + options: WriteProfileOptionsType ): Promise { const { server } = window.textsecure; if (!server) { @@ -46,16 +58,37 @@ export async function writeProfile( 'writeProfile: Cannot set an empty profile name' ); + let avatarUpdate: AvatarUpdateType; + if (options.keepAvatar) { + const profileAvatarPath = getAbsoluteProfileAvatarPath(model.attributes); + + let avatarBuffer: Uint8Array | undefined; + if (profileAvatarPath) { + try { + avatarBuffer = await imagePathToBytes(profileAvatarPath); + } catch (error) { + log.warn('writeProfile: local avatar not found, dropping remote'); + } + } + + avatarUpdate = { + oldAvatar: avatarBuffer, + newAvatar: avatarBuffer, + }; + } else { + avatarUpdate = options.avatarUpdate; + } + const [profileData, encryptedAvatarData] = await encryptProfileData( conversation, - avatar + avatarUpdate ); const avatarRequestHeaders = await server.putProfile(profileData); // Upload the avatar if provided // delete existing files on disk if avatar has been removed // update the account's avatar path and hash if it's a new avatar - const { newAvatar } = avatar; + const { newAvatar } = avatarUpdate; let maybeProfileAvatarUpdate: { profileAvatar?: | { diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index f94dfcce5..bc4dba1f7 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -2029,7 +2029,7 @@ function saveAvatarToDisk( function myProfileChanged( profileData: ProfileDataType, - avatar: AvatarUpdateType + avatarUpdate: AvatarUpdateType ): ThunkAction< void, RootStateType, @@ -2045,7 +2045,9 @@ function myProfileChanged( ...conversation, ...profileData, }, - avatar + { + avatarUpdate, + } ); // writeProfile above updates the backbone model which in turn updates diff --git a/ts/util/createIPCEvents.ts b/ts/util/createIPCEvents.ts index 55e1215cc..5a2fef867 100644 --- a/ts/util/createIPCEvents.ts +++ b/ts/util/createIPCEvents.ts @@ -242,8 +242,7 @@ export function createIPCEvents( // writeProfile fetches the latest profile first so do it before updating // local data to prevent triggering a conflict. await writeProfile(getConversation(account), { - oldAvatar: undefined, - newAvatar: undefined, + keepAvatar: true, }); const promises = new Array>();