feat: Add user metadata changing display name and description with sync
All checks were successful
Queue Release Build / prepare (push) Successful in 28s
Deploy Web Apps / deploy (push) Successful in 5m2s
Queue Release Build / build-windows (push) Successful in 16m44s
Queue Release Build / build-linux (push) Successful in 27m12s
Queue Release Build / finalize (push) Successful in 22s
All checks were successful
Queue Release Build / prepare (push) Successful in 28s
Deploy Web Apps / deploy (push) Successful in 5m2s
Queue Release Build / build-windows (push) Successful in 16m44s
Queue Release Build / build-linux (push) Successful in 27m12s
Queue Release Build / finalize (push) Successful in 22s
This commit is contained in:
@@ -37,6 +37,69 @@ interface AvatarFields {
|
||||
avatarUpdatedAt?: number;
|
||||
}
|
||||
|
||||
interface ProfileFields {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
profileUpdatedAt?: number;
|
||||
}
|
||||
|
||||
function hasOwnProperty(object: object, key: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(object, key);
|
||||
}
|
||||
|
||||
function normalizeProfileUpdatedAt(value: unknown): number | undefined {
|
||||
return typeof value === 'number' && Number.isFinite(value) && value > 0
|
||||
? value
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeDisplayName(value: unknown): string | undefined {
|
||||
if (typeof value !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const normalized = value.trim().replace(/\s+/g, ' ');
|
||||
|
||||
return normalized || undefined;
|
||||
}
|
||||
|
||||
function normalizeDescription(value: unknown): string | undefined {
|
||||
if (typeof value !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const normalized = value.trim();
|
||||
|
||||
return normalized || undefined;
|
||||
}
|
||||
|
||||
function mergeProfileFields(
|
||||
existingValue: Partial<ProfileFields> | undefined,
|
||||
incomingValue: Partial<ProfileFields>,
|
||||
preferIncomingFallback = true
|
||||
): ProfileFields {
|
||||
const existingUpdatedAt = normalizeProfileUpdatedAt(existingValue?.profileUpdatedAt) ?? 0;
|
||||
const incomingUpdatedAt = normalizeProfileUpdatedAt(incomingValue.profileUpdatedAt) ?? 0;
|
||||
const preferIncoming = incomingUpdatedAt === existingUpdatedAt
|
||||
? preferIncomingFallback
|
||||
: incomingUpdatedAt > existingUpdatedAt;
|
||||
const existingDisplayName = normalizeDisplayName(existingValue?.displayName);
|
||||
const incomingDisplayName = normalizeDisplayName(incomingValue.displayName);
|
||||
const existingDescription = normalizeDescription(existingValue?.description);
|
||||
const incomingHasDescription = hasOwnProperty(incomingValue, 'description');
|
||||
const incomingDescription = normalizeDescription(incomingValue.description);
|
||||
|
||||
return {
|
||||
displayName: preferIncoming
|
||||
? (incomingDisplayName || existingDisplayName || 'User')
|
||||
: (existingDisplayName || incomingDisplayName || 'User'),
|
||||
description: preferIncoming
|
||||
? (incomingHasDescription ? incomingDescription : existingDescription)
|
||||
: existingDescription,
|
||||
profileUpdatedAt: Math.max(existingUpdatedAt, incomingUpdatedAt) || undefined
|
||||
};
|
||||
}
|
||||
|
||||
function mergeAvatarFields(
|
||||
existingValue: AvatarFields | undefined,
|
||||
incomingValue: AvatarFields,
|
||||
@@ -112,10 +175,12 @@ function buildPresenceAwareUser(existingUser: User | undefined, incomingUser: Us
|
||||
? incomingUser.status
|
||||
: (existingUser?.status && existingUser.status !== 'offline' ? existingUser.status : 'online'))
|
||||
: 'offline';
|
||||
const profileFields = mergeProfileFields(existingUser, incomingUser, true);
|
||||
|
||||
return {
|
||||
...existingUser,
|
||||
...incomingUser,
|
||||
...profileFields,
|
||||
...mergeAvatarFields(existingUser, incomingUser, true),
|
||||
presenceServerIds,
|
||||
isOnline,
|
||||
@@ -128,17 +193,21 @@ function buildAvatarUser(existingUser: User | undefined, incomingUser: {
|
||||
oderId: string;
|
||||
username: string;
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
description?: string;
|
||||
profileUpdatedAt?: number;
|
||||
avatarUrl?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
}): User {
|
||||
const profileFields = mergeProfileFields(existingUser, incomingUser, true);
|
||||
|
||||
return {
|
||||
...existingUser,
|
||||
id: incomingUser.id,
|
||||
oderId: incomingUser.oderId,
|
||||
username: incomingUser.username || existingUser?.username || 'user',
|
||||
displayName: incomingUser.displayName || existingUser?.displayName || 'User',
|
||||
...profileFields,
|
||||
status: existingUser?.status ?? 'offline',
|
||||
role: existingUser?.role ?? 'member',
|
||||
joinedAt: existingUser?.joinedAt ?? Date.now(),
|
||||
@@ -230,6 +299,18 @@ export const usersReducer = createReducer(
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.updateCurrentUserProfile, (state, { profile }) => {
|
||||
if (!state.currentUserId)
|
||||
return state;
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: state.currentUserId,
|
||||
changes: mergeProfileFields(state.entities[state.currentUserId], profile, true)
|
||||
},
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.updateCurrentUserAvatar, (state, { avatar }) => {
|
||||
if (!state.currentUserId)
|
||||
return state;
|
||||
|
||||
Reference in New Issue
Block a user