mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 04:15:25 +00:00
enh: message reaction user names
This commit is contained in:
parent
fb6b18faef
commit
05e79bdd0c
3 changed files with 63 additions and 17 deletions
|
|
@ -5,7 +5,7 @@ from typing import Optional
|
|||
|
||||
from open_webui.internal.db import Base, get_db
|
||||
from open_webui.models.tags import TagModel, Tag, Tags
|
||||
from open_webui.models.users import Users, UserNameResponse
|
||||
from open_webui.models.users import Users, User, UserNameResponse
|
||||
from open_webui.models.channels import Channels, ChannelMember
|
||||
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ class MessageForm(BaseModel):
|
|||
|
||||
class Reactions(BaseModel):
|
||||
name: str
|
||||
user_ids: list[str]
|
||||
users: list[dict]
|
||||
count: int
|
||||
|
||||
|
||||
|
|
@ -389,17 +389,30 @@ class MessageTable:
|
|||
|
||||
def get_reactions_by_message_id(self, id: str) -> list[Reactions]:
|
||||
with get_db() as db:
|
||||
all_reactions = db.query(MessageReaction).filter_by(message_id=id).all()
|
||||
# JOIN User so all user info is fetched in one query
|
||||
results = (
|
||||
db.query(MessageReaction, User)
|
||||
.join(User, MessageReaction.user_id == User.id)
|
||||
.filter(MessageReaction.message_id == id)
|
||||
.all()
|
||||
)
|
||||
|
||||
reactions = {}
|
||||
for reaction in all_reactions:
|
||||
|
||||
for reaction, user in results:
|
||||
if reaction.name not in reactions:
|
||||
reactions[reaction.name] = {
|
||||
"name": reaction.name,
|
||||
"user_ids": [],
|
||||
"users": [],
|
||||
"count": 0,
|
||||
}
|
||||
reactions[reaction.name]["user_ids"].append(reaction.user_id)
|
||||
|
||||
reactions[reaction.name]["users"].append(
|
||||
{
|
||||
"id": user.id,
|
||||
"name": user.name,
|
||||
}
|
||||
)
|
||||
reactions[reaction.name]["count"] += 1
|
||||
|
||||
return [Reactions(**reaction) for reaction in reactions.values()]
|
||||
|
|
|
|||
|
|
@ -197,8 +197,8 @@
|
|||
const reaction = m.reactions.find((reaction) => reaction.name === name);
|
||||
|
||||
if (reaction) {
|
||||
reaction.user_ids = reaction.user_ids.filter((id) => id !== $user?.id);
|
||||
reaction.count = reaction.user_ids.length;
|
||||
reaction.users = reaction.users.filter((u) => u.id !== $user?.id);
|
||||
reaction.count = reaction.users.length;
|
||||
|
||||
if (reaction.count === 0) {
|
||||
m.reactions = m.reactions.filter((r) => r.name !== name);
|
||||
|
|
@ -224,12 +224,12 @@
|
|||
const reaction = m.reactions.find((reaction) => reaction.name === name);
|
||||
|
||||
if (reaction) {
|
||||
reaction.user_ids.push($user?.id);
|
||||
reaction.count = reaction.user_ids.length;
|
||||
reaction.users.push({ id: $user?.id, name: $user?.name });
|
||||
reaction.count = reaction.users.length;
|
||||
} else {
|
||||
m.reactions.push({
|
||||
name: name,
|
||||
user_ids: [$user?.id],
|
||||
users: [{ id: $user?.id, name: $user?.name }],
|
||||
count: 1
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -398,11 +398,44 @@
|
|||
<div>
|
||||
<div class="flex items-center flex-wrap gap-y-1.5 gap-1 mt-1 mb-2">
|
||||
{#each message.reactions as reaction}
|
||||
<Tooltip content={`:${reaction.name}:`}>
|
||||
<Tooltip
|
||||
content={$i18n.t('{{NAMES}} reacted with {{REACTION}}', {
|
||||
NAMES: reaction.users
|
||||
.reduce((acc, u, idx) => {
|
||||
const name = u.id === $user?.id ? $i18n.t('You') : u.name;
|
||||
const total = reaction.users.length;
|
||||
|
||||
// First three names always added normally
|
||||
if (idx < 3) {
|
||||
const separator =
|
||||
idx === 0
|
||||
? ''
|
||||
: idx === Math.min(2, total - 1)
|
||||
? ` ${$i18n.t('and')} `
|
||||
: ', ';
|
||||
return `${acc}${separator}${name}`;
|
||||
}
|
||||
|
||||
// More than 4 → "and X others"
|
||||
if (idx === 3 && total > 4) {
|
||||
return (
|
||||
acc +
|
||||
` ${$i18n.t('and {{COUNT}} others', {
|
||||
COUNT: total - 3
|
||||
})}`
|
||||
);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, '')
|
||||
.trim(),
|
||||
REACTION: `:${reaction.name}:`
|
||||
})}
|
||||
>
|
||||
<button
|
||||
class="flex items-center gap-1.5 transition rounded-xl px-2 py-1 cursor-pointer {reaction.user_ids.includes(
|
||||
$user?.id
|
||||
)
|
||||
class="flex items-center gap-1.5 transition rounded-xl px-2 py-1 cursor-pointer {reaction.users
|
||||
.map((u) => u.id)
|
||||
.includes($user?.id)
|
||||
? ' bg-blue-300/10 outline outline-blue-500/50 outline-1'
|
||||
: 'bg-gray-300/10 dark:bg-gray-500/10 hover:outline hover:outline-gray-700/30 dark:hover:outline-gray-300/30 hover:outline-1'}"
|
||||
on:click={() => {
|
||||
|
|
@ -413,9 +446,9 @@
|
|||
>
|
||||
<Emoji shortCode={reaction.name} />
|
||||
|
||||
{#if reaction.user_ids.length > 0}
|
||||
{#if reaction.users.length > 0}
|
||||
<div class="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
{reaction.user_ids?.length}
|
||||
{reaction.users?.length}
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue