Skip to content

Commit b3cc370

Browse files
committed
feat: show profile pic upload failed for user avatar change
1 parent e1a2163 commit b3cc370

File tree

7 files changed

+53
-9
lines changed

7 files changed

+53
-9
lines changed

ts/components/SessionInboxView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ async function createSessionInboxStore() {
7878
ourDisplayNameInProfile: UserUtils.getOurProfile()?.displayName || '',
7979
ourNumber: UserUtils.getOurPubKeyStrFromCache(),
8080
uploadingNewAvatarCurrentUser: false,
81+
uploadingNewAvatarCurrentUserFailed: false,
8182
},
8283
section: initialSectionState,
8384
defaultRooms: initialDefaultRoomState,

ts/components/dialog/EditProfilePictureModal.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { groupInfoActions } from '../../state/ducks/metaGroups';
2222
import { useGroupAvatarChangeFromUIPending } from '../../state/selectors/groups';
2323
import { userActions } from '../../state/ducks/user';
2424
import { ReduxSogsRoomInfos } from '../../state/ducks/sogsRoomInfo';
25-
import { useOurAvatarIsUploading } from '../../state/selectors/user';
25+
import { useOurAvatarIsUploading, useOurAvatarUploadFailed } from '../../state/selectors/user';
2626
import { useAvatarOfRoomIsUploading } from '../../state/selectors/sogsRoomInfo';
2727
import {
2828
ModalActionsContainer,
@@ -41,6 +41,9 @@ import { useProBadgeOnClickCb } from '../menuAndSettingsHooks/useProBadgeOnClick
4141
import { useUserHasPro } from '../../hooks/useHasPro';
4242
import { Localizer } from '../basic/Localizer';
4343
import { UploadFirstImageButton } from '../buttons/avatar/UploadFirstImageButton';
44+
import { Flex } from '../basic/Flex';
45+
import { LucideIcon } from '../icon/LucideIcon';
46+
import { LUCIDE_ICONS_UNICODE } from '../icon/lucide';
4447

4548
const StyledAvatarContainer = styled.div`
4649
cursor: pointer;
@@ -142,6 +145,7 @@ export const EditProfilePictureModal = ({ conversationId }: EditProfilePictureMo
142145

143146
const groupAvatarChangePending = useGroupAvatarChangeFromUIPending();
144147
const ourAvatarIsUploading = useOurAvatarIsUploading();
148+
const ourAvatarUploadFailed = useOurAvatarUploadFailed();
145149
const sogsAvatarIsUploading = useAvatarOfRoomIsUploading(conversationId);
146150

147151
const [newAvatarObjectUrl, setNewAvatarObjectUrl] = useState<string | null>(avatarPath);
@@ -312,7 +316,21 @@ export const EditProfilePictureModal = ({ conversationId }: EditProfilePictureMo
312316
)}
313317
</StyledAvatarContainer>
314318
</div>
315-
{}
319+
{ourAvatarUploadFailed && isMe ? (
320+
<Flex
321+
$container={true}
322+
$justifyContent="center"
323+
$alignItems="center"
324+
$flexGap="var(--margins-xs)"
325+
style={{
326+
marginTop: 'var(--margins-lg)',
327+
color: 'var(--danger-color)',
328+
}}
329+
>
330+
<LucideIcon unicode={LUCIDE_ICONS_UNICODE.TRIANGLE_ALERT} iconSize="small" />
331+
<Localizer token="profileErrorUpdate" />
332+
</Flex>
333+
) : null}
316334
{loading ? (
317335
<>
318336
<SpacerSM />

ts/components/dialog/UpdateConversationDetailsDialog.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useState } from 'react';
33
import { useDispatch } from 'react-redux';
44
import useKey from 'react-use/lib/useKey';
55
import useMount from 'react-use/lib/useMount';
6+
import { isEmpty } from 'lodash';
67

78
import {
89
useAvatarPath,
@@ -42,6 +43,8 @@ import {
4243
import { ReduxSogsRoomInfos } from '../../state/ducks/sogsRoomInfo';
4344
import type { WithConvoId } from '../../session/types/with';
4445
import { UploadFirstImageButton } from '../buttons/avatar/UploadFirstImageButton';
46+
import { sanitizeDisplayNameOrToast } from '../registration/utils';
47+
import { ProfileManager } from '../../session/profile_manager/ProfileManager';
4548

4649
function useNameErrorString({
4750
isMe,
@@ -164,6 +167,21 @@ export function UpdateConversationDetailsDialog(props: WithConvoId) {
164167
}
165168

166169
if (trimmedGroupName !== nameOnOpen || trimmedGroupDescription !== descriptionOnOpen) {
170+
if (isMe) {
171+
const sanitizedName = sanitizeDisplayNameOrToast(trimmedGroupName);
172+
173+
// this should never happen, but just in case
174+
if (isEmpty(sanitizedName)) {
175+
return;
176+
}
177+
178+
// this truncates if the display name is too long
179+
// Note: this not doing any network calls. No need for a loader in this case
180+
void ProfileManager.updateOurProfileDisplayName(sanitizedName);
181+
closeDialog();
182+
183+
return;
184+
}
167185
if (isPublic) {
168186
const updateDetailsAction = ReduxSogsRoomInfos.roomDetailsChange({
169187
conversationId,

ts/components/dialog/user-settings/pages/DefaultSettingsPage.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,6 @@ export const DefaultSettingPage = () => {
385385
conversationId={us}
386386
onPlusAvatarClick={null}
387387
dataTestId="avatar-edit-profile-dialog"
388-
// no qr click here as a button is already doing that action (and the qr button looks bad when the small size as the +)
389-
// Note: this changes with the new Settings design
390388
onQRClick={() => setMode('qr')}
391389
enlargedImage={enlargedImage}
392390
toggleEnlargedImage={() => setEnlargedImage(!enlargedImage)}

ts/session/profile_manager/ProfileManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ async function updateOurProfileDisplayName(newName: string) {
161161

162162
// might be good to not trigger a sync if the name did not change
163163
await conversation.commit();
164-
await SyncUtils.forceSyncConfigurationNowIfNeeded(true);
164+
void SyncUtils.forceSyncConfigurationNowIfNeeded(true);
165165

166166
return truncatedName;
167167
}

ts/state/ducks/user.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ export type UserStateType = {
1111
ourDisplayNameInProfile: string;
1212
ourNumber: string;
1313
uploadingNewAvatarCurrentUser: boolean;
14+
uploadingNewAvatarCurrentUserFailed: boolean;
1415
};
1516

1617
export const initialUserState: UserStateType = {
1718
ourDisplayNameInProfile: '',
1819
ourNumber: 'missing',
1920
uploadingNewAvatarCurrentUser: false,
21+
uploadingNewAvatarCurrentUserFailed: false,
2022
};
2123

2224
/**
@@ -43,9 +45,10 @@ const updateOurAvatar = createAsyncThunk(
4345
profileKey,
4446
});
4547

46-
window.inboxStore?.dispatch(updateEditProfilePictureModal(null));
47-
window.inboxStore?.dispatch(userSettingsModal({ userSettingsPage: 'default' }));
48-
48+
if (res) {
49+
window.inboxStore?.dispatch(updateEditProfilePictureModal(null));
50+
window.inboxStore?.dispatch(userSettingsModal({ userSettingsPage: 'default' }));
51+
}
4952
return res;
5053
}
5154
);
@@ -111,16 +114,18 @@ const userSlice = createSlice({
111114
window.log.info('a updateOurAvatar was fulfilled with:', action.payload);
112115

113116
state.uploadingNewAvatarCurrentUser = false;
117+
state.uploadingNewAvatarCurrentUserFailed = !action.payload;
114118
return state;
115119
});
116120
builder.addCase(updateOurAvatar.rejected, (state, action) => {
117121
window.log.error('a updateOurAvatar was rejected', action.error);
118122
state.uploadingNewAvatarCurrentUser = false;
123+
state.uploadingNewAvatarCurrentUserFailed = true;
119124
return state;
120125
});
121126
builder.addCase(updateOurAvatar.pending, (state, _action) => {
122127
state.uploadingNewAvatarCurrentUser = true;
123-
128+
state.uploadingNewAvatarCurrentUserFailed = false;
124129
window.log.debug('a updateOurAvatar is pending');
125130
return state;
126131
});

ts/state/selectors/user.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ export function useOurPkStr() {
2525
export function useOurAvatarIsUploading() {
2626
return useSelector((state: StateType) => getUser(state).uploadingNewAvatarCurrentUser);
2727
}
28+
29+
export function useOurAvatarUploadFailed() {
30+
return useSelector((state: StateType) => getUser(state).uploadingNewAvatarCurrentUserFailed);
31+
}

0 commit comments

Comments
 (0)