feat: Add profile images
This commit is contained in:
@@ -30,6 +30,39 @@ function mergePresenceServerIds(
|
||||
return normalizePresenceServerIds([...(existingServerIds ?? []), ...(incomingServerIds ?? [])]);
|
||||
}
|
||||
|
||||
interface AvatarFields {
|
||||
avatarUrl?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
}
|
||||
|
||||
function mergeAvatarFields(
|
||||
existingValue: AvatarFields | undefined,
|
||||
incomingValue: AvatarFields,
|
||||
preferIncomingFallback = true
|
||||
): AvatarFields {
|
||||
const existingUpdatedAt = existingValue?.avatarUpdatedAt ?? 0;
|
||||
const incomingUpdatedAt = incomingValue.avatarUpdatedAt ?? 0;
|
||||
const preferIncoming = incomingUpdatedAt === existingUpdatedAt
|
||||
? preferIncomingFallback
|
||||
: incomingUpdatedAt > existingUpdatedAt;
|
||||
|
||||
return {
|
||||
avatarUrl: preferIncoming
|
||||
? (incomingValue.avatarUrl || existingValue?.avatarUrl)
|
||||
: (existingValue?.avatarUrl || incomingValue.avatarUrl),
|
||||
avatarHash: preferIncoming
|
||||
? (incomingValue.avatarHash || existingValue?.avatarHash)
|
||||
: (existingValue?.avatarHash || incomingValue.avatarHash),
|
||||
avatarMime: preferIncoming
|
||||
? (incomingValue.avatarMime || existingValue?.avatarMime)
|
||||
: (existingValue?.avatarMime || incomingValue.avatarMime),
|
||||
|
||||
avatarUpdatedAt: Math.max(existingUpdatedAt, incomingUpdatedAt) || undefined
|
||||
};
|
||||
}
|
||||
|
||||
function buildDisconnectedVoiceState(user: User): User['voiceState'] {
|
||||
if (!user.voiceState) {
|
||||
return undefined;
|
||||
@@ -83,12 +116,36 @@ function buildPresenceAwareUser(existingUser: User | undefined, incomingUser: Us
|
||||
return {
|
||||
...existingUser,
|
||||
...incomingUser,
|
||||
...mergeAvatarFields(existingUser, incomingUser, true),
|
||||
presenceServerIds,
|
||||
isOnline,
|
||||
status
|
||||
};
|
||||
}
|
||||
|
||||
function buildAvatarUser(existingUser: User | undefined, incomingUser: {
|
||||
id: string;
|
||||
oderId: string;
|
||||
username: string;
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
}): User {
|
||||
return {
|
||||
...existingUser,
|
||||
id: incomingUser.id,
|
||||
oderId: incomingUser.oderId,
|
||||
username: incomingUser.username || existingUser?.username || 'user',
|
||||
displayName: incomingUser.displayName || existingUser?.displayName || 'User',
|
||||
status: existingUser?.status ?? 'offline',
|
||||
role: existingUser?.role ?? 'member',
|
||||
joinedAt: existingUser?.joinedAt ?? Date.now(),
|
||||
...mergeAvatarFields(existingUser, incomingUser, true)
|
||||
};
|
||||
}
|
||||
|
||||
function buildPresenceRemovalChanges(
|
||||
user: User,
|
||||
update: { serverId?: string; serverIds?: readonly string[] }
|
||||
@@ -173,6 +230,18 @@ export const usersReducer = createReducer(
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.updateCurrentUserAvatar, (state, { avatar }) => {
|
||||
if (!state.currentUserId)
|
||||
return state;
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: state.currentUserId,
|
||||
changes: mergeAvatarFields(state.entities[state.currentUserId], avatar, true)
|
||||
},
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.loadRoomUsers, (state) => ({
|
||||
...state,
|
||||
loading: true,
|
||||
@@ -256,6 +325,9 @@ export const usersReducer = createReducer(
|
||||
state
|
||||
)
|
||||
),
|
||||
on(UsersActions.upsertRemoteUserAvatar, (state, { user }) =>
|
||||
usersAdapter.upsertOne(buildAvatarUser(state.entities[user.id], user), state)
|
||||
),
|
||||
on(UsersActions.updateUserRole, (state, { userId, role }) =>
|
||||
usersAdapter.updateOne(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user