From 4b6773885cd7527c5a56b963781dac5e95105eec Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 28 Nov 2025 04:24:25 -0500 Subject: [PATCH] enh: dm active user indicator --- backend/open_webui/models/users.py | 6 +++++ backend/open_webui/routers/channels.py | 10 ++++++-- .../layout/Sidebar/ChannelItem.svelte | 23 +++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/models/users.py b/backend/open_webui/models/users.py index 2fa634097c..e7beeee1bf 100644 --- a/backend/open_webui/models/users.py +++ b/backend/open_webui/models/users.py @@ -125,6 +125,12 @@ class UserIdNameResponse(BaseModel): name: str +class UserIdNameStatusResponse(BaseModel): + id: str + name: str + is_active: bool + + class UserInfoListResponse(BaseModel): users: list[UserInfoResponse] total: int diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index 1bf905155e..a3228f5c80 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -14,6 +14,7 @@ from open_webui.socket.main import ( ) from open_webui.models.users import ( UserIdNameResponse, + UserIdNameStatusResponse, UserListResponse, UserModelResponse, Users, @@ -68,7 +69,7 @@ router = APIRouter() class ChannelListItemResponse(ChannelModel): user_ids: Optional[list[str]] = None # 'dm' channels only - users: Optional[list[UserIdNameResponse]] = None # 'dm' channels only + users: Optional[list[UserIdNameStatusResponse]] = None # 'dm' channels only last_message_at: Optional[int] = None # timestamp in epoch (time_ns) unread_count: int = 0 @@ -97,7 +98,12 @@ async def get_channels(user=Depends(get_verified_user)): for member in Channels.get_members_by_channel_id(channel.id) ] users = [ - UserIdNameResponse(**user.model_dump()) + UserIdNameStatusResponse( + **{ + **user.model_dump(), + "is_active": get_active_status_by_user_id(user.id), + } + ) for user in Users.get_users_by_user_ids(user_ids) ] diff --git a/src/lib/components/layout/Sidebar/ChannelItem.svelte b/src/lib/components/layout/Sidebar/ChannelItem.svelte index 11030727eb..cf148658b8 100644 --- a/src/lib/components/layout/Sidebar/ChannelItem.svelte +++ b/src/lib/components/layout/Sidebar/ChannelItem.svelte @@ -5,6 +5,7 @@ import { page } from '$app/stores'; import { channels, mobile, showSidebar, user } from '$lib/stores'; + import { getUserActiveStatusById } from '$lib/apis/users'; import { updateChannelById, updateChannelMemberActiveStatusById } from '$lib/apis/channels'; import { WEBUI_API_BASE_URL } from '$lib/constants'; @@ -83,8 +84,9 @@
{#if channel?.type === 'dm'} {#if channel?.users} -
- {#each channel.users.filter((u) => u.id !== $user?.id).slice(0, 2) as u, index} + {@const channelMembers = channel.users.filter((u) => u.id !== $user?.id)} +
+ {#each channelMembers.slice(0, 2) as u, index} {u.name} {/each} + + {#if channelMembers.length === 1} +
+ + {#if channelMembers[0]?.is_active} + + {/if} + + +
+ {/if}
{:else}