mirror of
https://github.com/lux-tel/session-desktop.git
synced 2026-10-30 20:33:24 +00:00
165 lines
5.3 KiB
TypeScript
165 lines
5.3 KiB
TypeScript
import { isNil } from 'lodash';
|
|
import { createAsyncThunk, createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
|
import { ConvoHub } from '../../session/conversations';
|
|
import { SyncUtils, UserUtils } from '../../session/utils';
|
|
import { uploadAndSetOurAvatarShared } from '../../interactions/avatar-interactions/nts-avatar-interactions';
|
|
import { ed25519Str } from '../../session/utils/String';
|
|
import { userSettingsModal, updateEditProfilePictureModal } from './modalDialog';
|
|
import { NetworkTime } from '../../util/NetworkTime';
|
|
import { UserConfigWrapperActions } from '../../webworker/workers/browser/libsession/libsession_worker_userconfig_interface';
|
|
import { SessionProfileResetAvatarPrivate } from '../../models/profile';
|
|
|
|
export type UserStateType = {
|
|
ourDisplayNameInProfile: string;
|
|
ourNumber: string;
|
|
uploadingNewAvatarCurrentUser: boolean;
|
|
uploadingNewAvatarCurrentUserFailed: boolean;
|
|
};
|
|
|
|
export const initialUserState: UserStateType = {
|
|
ourDisplayNameInProfile: '',
|
|
ourNumber: 'missing',
|
|
uploadingNewAvatarCurrentUser: false,
|
|
uploadingNewAvatarCurrentUserFailed: false,
|
|
};
|
|
|
|
/**
|
|
* updateOurAvatar is called when the user is, from the current device, changing his avatar.
|
|
* Note: auto reupload is not done here, as we do not need a UI for it.
|
|
*
|
|
*/
|
|
const updateOurAvatar = createAsyncThunk(
|
|
'user/updateOurAvatar',
|
|
async ({ mainAvatarDecrypted }: { mainAvatarDecrypted: ArrayBuffer }) => {
|
|
const ourConvo = ConvoHub.use().get(UserUtils.getOurPubKeyStrFromCache());
|
|
if (!ourConvo) {
|
|
window.log.warn('ourConvo not found... This is not a valid case');
|
|
return null;
|
|
}
|
|
|
|
const res = await uploadAndSetOurAvatarShared({
|
|
decryptedAvatarData: mainAvatarDecrypted,
|
|
ourConvo,
|
|
context: 'uploadNewAvatar',
|
|
});
|
|
|
|
if (res) {
|
|
window.inboxStore?.dispatch(updateEditProfilePictureModal(null));
|
|
window.inboxStore?.dispatch(userSettingsModal({ userSettingsPage: 'default' }));
|
|
}
|
|
return res;
|
|
}
|
|
);
|
|
|
|
const clearOurAvatar = createAsyncThunk('user/clearOurAvatar', async () => {
|
|
const us = UserUtils.getOurPubKeyStrFromCache();
|
|
if (!us) {
|
|
window.log.warn('user/clearOurAvatar: invalid conversationId provided: ');
|
|
throw new Error('user/clearOurAvatar: invalid conversationId provided');
|
|
}
|
|
const convo = ConvoHub.use().get(us);
|
|
if (!convo) {
|
|
window.log.warn(
|
|
`clearOurAvatar: convo ${ed25519Str(us)} not found... This is not a valid case`
|
|
);
|
|
return;
|
|
}
|
|
|
|
// return early if no change are needed at all
|
|
if (
|
|
isNil(convo.getAvatarPointer()) &&
|
|
isNil(convo.getAvatarInProfilePath()) &&
|
|
isNil(convo.getFallbackAvatarInProfilePath()) &&
|
|
isNil(convo.getProfileKeyHex())
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const profile = new SessionProfileResetAvatarPrivate({
|
|
convo,
|
|
displayName: null,
|
|
profileUpdatedAtSeconds: NetworkTime.nowSeconds(),
|
|
// NTS case, we don't care about those
|
|
proDetails: { bitsetProFeatures: null, proExpiryTsMs: null, proGenIndexHashB64: null },
|
|
});
|
|
|
|
await profile.applyChangesIfNeeded();
|
|
|
|
await UserConfigWrapperActions.setNewProfilePic({
|
|
url: null,
|
|
key: null,
|
|
});
|
|
|
|
await SyncUtils.forceSyncConfigurationNowIfNeeded(true);
|
|
window.inboxStore?.dispatch(updateEditProfilePictureModal(null));
|
|
});
|
|
|
|
/**
|
|
* This slice is representing the state of our user account.
|
|
* It also contains the loading states of the changes being made to it.
|
|
*/
|
|
const userSlice = createSlice({
|
|
name: 'userSlice',
|
|
initialState: initialUserState,
|
|
reducers: {
|
|
userChanged(
|
|
state: UserStateType,
|
|
action: PayloadAction<{
|
|
ourDisplayNameInProfile: string;
|
|
ourNumber: string;
|
|
}>
|
|
) {
|
|
return {
|
|
...state,
|
|
...action.payload,
|
|
};
|
|
},
|
|
},
|
|
extraReducers: builder => {
|
|
builder.addCase(updateOurAvatar.fulfilled, (state, action) => {
|
|
window.log.info('a updateOurAvatar was fulfilled with:', action.payload);
|
|
|
|
state.uploadingNewAvatarCurrentUser = false;
|
|
state.uploadingNewAvatarCurrentUserFailed = !action.payload;
|
|
return state;
|
|
});
|
|
builder.addCase(updateOurAvatar.rejected, (state, action) => {
|
|
window.log.error('a updateOurAvatar was rejected', action.error);
|
|
state.uploadingNewAvatarCurrentUser = false;
|
|
state.uploadingNewAvatarCurrentUserFailed = true;
|
|
return state;
|
|
});
|
|
builder.addCase(updateOurAvatar.pending, (state, _action) => {
|
|
state.uploadingNewAvatarCurrentUser = true;
|
|
state.uploadingNewAvatarCurrentUserFailed = false;
|
|
window.log.debug('a updateOurAvatar is pending');
|
|
return state;
|
|
});
|
|
builder.addCase(clearOurAvatar.fulfilled, (state, action) => {
|
|
window.log.debug('a clearOurAvatar was fulfilled with:', action.payload);
|
|
|
|
state.uploadingNewAvatarCurrentUser = false;
|
|
return state;
|
|
});
|
|
builder.addCase(clearOurAvatar.rejected, (state, action) => {
|
|
window.log.error('a clearOurAvatar was rejected', action.error);
|
|
state.uploadingNewAvatarCurrentUser = false;
|
|
return state;
|
|
});
|
|
builder.addCase(clearOurAvatar.pending, (state, _action) => {
|
|
state.uploadingNewAvatarCurrentUser = true;
|
|
|
|
window.log.debug('a clearOurAvatar is pending');
|
|
return state;
|
|
});
|
|
},
|
|
});
|
|
|
|
export const userActions = {
|
|
...userSlice.actions,
|
|
updateOurAvatar,
|
|
clearOurAvatar,
|
|
};
|
|
|
|
export const userReducer = userSlice.reducer;
|