mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-10 03:27:57 +00:00
refac
This commit is contained in:
parent
a53e453a26
commit
538f9c9090
5 changed files with 97 additions and 15 deletions
|
|
@ -310,6 +310,8 @@ class UserInfoResponse(UserStatus):
|
|||
email: str
|
||||
role: str
|
||||
bio: str | None = None
|
||||
last_active_at: int | None = None
|
||||
timezone: str | None = None
|
||||
groups: list | None = []
|
||||
is_active: bool = False
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,61 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
const i18n = getContext<typeof import('$lib/i18n').default>('i18n');
|
||||
|
||||
import { user as _user } from '$lib/stores';
|
||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
||||
import { getDMChannelByUserId } from '$lib/apis/channels';
|
||||
|
||||
import ChatBubbleOval from '$lib/components/icons/ChatBubbleOval.svelte';
|
||||
import ClockRotateRight from '$lib/components/icons/ClockRotateRight.svelte';
|
||||
import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import Emoji from '$lib/components/common/Emoji.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
|
||||
export let user = null;
|
||||
export let user: {
|
||||
id: string;
|
||||
name: string;
|
||||
is_active?: boolean;
|
||||
last_active_at?: number | null;
|
||||
timezone?: string | null;
|
||||
status_emoji?: string | null;
|
||||
status_message?: string | null;
|
||||
bio?: string | null;
|
||||
groups?: { name: string }[] | null;
|
||||
} | null = null;
|
||||
|
||||
let now = new Date();
|
||||
let localTime = '';
|
||||
|
||||
$: lastSeen = user?.last_active_at
|
||||
? new Date(user.last_active_at * 1000).toLocaleString($i18n.language, {
|
||||
dateStyle: 'medium',
|
||||
timeStyle: 'short'
|
||||
})
|
||||
: '';
|
||||
|
||||
$: {
|
||||
localTime = '';
|
||||
if (user?.timezone) {
|
||||
try {
|
||||
localTime = now.toLocaleTimeString($i18n.language, {
|
||||
timeZone: user.timezone,
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
timeZoneName: 'short'
|
||||
});
|
||||
} catch {
|
||||
// Older profiles may contain a timezone the browser cannot resolve.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const interval = setInterval(() => (now = new Date()), 30_000);
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
const directMessageHandler = async () => {
|
||||
if (!user) {
|
||||
|
|
@ -62,7 +105,7 @@
|
|||
|
||||
{#if user.status_emoji || user.status_message}
|
||||
<div class="mt-2.5">
|
||||
<Tooltip content={user.status_message}>
|
||||
<Tooltip content={user.status_message ?? undefined}>
|
||||
<div class="flex min-w-0 items-start gap-1.5 text-gray-700 dark:text-gray-300">
|
||||
{#if user.status_emoji}
|
||||
<div class="flex h-4 shrink-0 items-center">
|
||||
|
|
@ -100,16 +143,47 @@
|
|||
{/if}
|
||||
</div>
|
||||
|
||||
{#if $_user?.id !== user.id}
|
||||
{#if lastSeen || localTime || $_user?.id !== user.id}
|
||||
<div class="border-t border-gray-50/60 p-1.5 dark:border-gray-800/30">
|
||||
<button
|
||||
class="flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left text-xs text-gray-700 transition-colors hover:bg-gray-50/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 dark:text-gray-300 dark:hover:bg-gray-800/60"
|
||||
type="button"
|
||||
on:click={directMessageHandler}
|
||||
>
|
||||
<ChatBubbleOval className="size-3.5 shrink-0" />
|
||||
<span>{$i18n.t('Message')}</span>
|
||||
</button>
|
||||
{#if lastSeen || localTime}
|
||||
<dl class="text-[0.625rem] leading-[0.875rem] text-gray-500 dark:text-gray-400">
|
||||
{#if localTime}
|
||||
<div class="flex items-start gap-1.5 px-1.5 py-0.5">
|
||||
<dt class="shrink-0 pt-px">
|
||||
<Tooltip content={$i18n.t('Local time')}>
|
||||
<GlobeAlt className="size-3" />
|
||||
<span class="sr-only">{$i18n.t('Local time')}</span>
|
||||
</Tooltip>
|
||||
</dt>
|
||||
<dd title={user.timezone}>{localTime}</dd>
|
||||
</div>
|
||||
{/if}
|
||||
{#if lastSeen}
|
||||
<div class="flex items-start gap-1.5 px-1.5 py-0.5">
|
||||
<dt class="shrink-0 pt-px">
|
||||
<Tooltip content={$i18n.t('Last seen')}>
|
||||
<ClockRotateRight className="size-3" />
|
||||
<span class="sr-only">{$i18n.t('Last seen')}</span>
|
||||
</Tooltip>
|
||||
</dt>
|
||||
<dd>{lastSeen}</dd>
|
||||
</div>
|
||||
{/if}
|
||||
</dl>
|
||||
{/if}
|
||||
{#if $_user?.id !== user.id}
|
||||
{#if lastSeen || localTime}
|
||||
<div class="-mx-1.5 my-1 border-t border-gray-50/60 dark:border-gray-800/30"></div>
|
||||
{/if}
|
||||
<button
|
||||
class="flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left text-xs text-gray-700 transition-colors hover:bg-gray-50/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 dark:text-gray-300 dark:hover:bg-gray-800/60"
|
||||
type="button"
|
||||
on:click={directMessageHandler}
|
||||
>
|
||||
<ChatBubbleOval className="size-3.5 shrink-0" />
|
||||
<span>{$i18n.t('Message')}</span>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
const loadUser = async (userId: string) => {
|
||||
requestedUserId = userId;
|
||||
user = null;
|
||||
|
||||
const loadedUser = await getUserInfoById(localStorage.token, userId).catch((error) => {
|
||||
if (requestedUserId === userId) {
|
||||
|
|
@ -35,6 +36,8 @@
|
|||
|
||||
$: if (openPreview && id && id !== requestedUserId) {
|
||||
loadUser(id);
|
||||
} else if (!openPreview) {
|
||||
requestedUserId = null;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
let idType = null;
|
||||
let id = '';
|
||||
let openPreview = false;
|
||||
|
||||
$: if (token && $i18n && $models && $channels) {
|
||||
init();
|
||||
|
|
@ -81,7 +82,7 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<LinkPreview.Root openDelay={0} closeDelay={0}>
|
||||
<LinkPreview.Root openDelay={0} closeDelay={0} bind:open={openPreview}>
|
||||
<LinkPreview.Trigger class=" cursor-pointer no-underline! font-normal! ">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
|
|
@ -117,6 +118,6 @@
|
|||
</LinkPreview.Trigger>
|
||||
|
||||
{#if triggerChar === '@' && idType === 'U'}
|
||||
<UserStatusLinkPreview {id} />
|
||||
<UserStatusLinkPreview {id} {openPreview} />
|
||||
{/if}
|
||||
</LinkPreview.Root>
|
||||
|
|
|
|||
|
|
@ -1328,6 +1328,7 @@
|
|||
"Last 7 days": "",
|
||||
"Last 90 days": "",
|
||||
"Last Active": "",
|
||||
"Last seen": "",
|
||||
"Last Modified": "",
|
||||
"Last reply": "",
|
||||
"Last run": "",
|
||||
|
|
@ -1376,6 +1377,7 @@
|
|||
"Loading release notes...": "",
|
||||
"Loading tools...": "",
|
||||
"Loading...": "",
|
||||
"Local time": "",
|
||||
"local": "",
|
||||
"Local": "",
|
||||
"Location": "",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue