import { reactive } from 'vue'; import type { OrgUserDto } from '@mento/shared'; import { api } from '@/lib/api'; import { useAuthStore } from '@/stores/auth'; export const DEFAULT_USER_AVATAR = '/brand/user-avatar.png'; /** userId → آیا عکس دارد (از فهرست کاربران سازمان) */ const hasAvatarById = reactive>({}); /** userId → object URL عکس */ const urlById = reactive>({}); const pending = new Map>(); let usersLoad: Promise | null = null; let usersScope: string | null = null; function resetCache() { for (const url of Object.values(urlById)) URL.revokeObjectURL(url); for (const key of Object.keys(urlById)) delete urlById[key]; for (const key of Object.keys(hasAvatarById)) delete hasAvatarById[key]; pending.clear(); usersLoad = null; } function ensureScope() { const auth = useAuthStore(); const scope = auth.user ? `${auth.user.id}:${auth.user.organizationId}` : null; if (scope !== usersScope) { resetCache(); usersScope = scope; } return auth; } function loadUserFlags(): Promise { if (usersLoad) return usersLoad; usersLoad = api .get('/users') .then(({ data }) => { for (const u of data ?? []) hasAvatarById[u.id] = Boolean(u.hasAvatar); }) .catch(() => undefined); return usersLoad; } function fetchAvatar(userId: string): Promise { const existing = pending.get(userId); if (existing) return existing; const job = api .get(`/users/${encodeURIComponent(userId)}/avatar`, { responseType: 'blob' }) .then(({ data }) => { if (!data || data.size === 0 || data.type.includes('json')) return; urlById[userId] = URL.createObjectURL(data); }) .catch(() => { hasAvatarById[userId] = false; }); pending.set(userId, job); return job; } /** اطلاع از وضعیت عکس کاربرانی که API برگردانده (مثلاً اعضای گفتگو). */ export function primeUserAvatar(userId: string, hasAvatar: boolean | undefined) { ensureScope(); if (hasAvatar === undefined) return; hasAvatarById[userId] = hasAvatar; } /** آدرس عکس پروفایل کاربر؛ تا بارگذاری نشده عکس پیش‌فرض برمی‌گردد. */ export function userAvatarSrc(userId: string | null | undefined): string { if (!userId) return DEFAULT_USER_AVATAR; const auth = ensureScope(); if (auth.user?.id === userId) return auth.avatarSrc; const url = urlById[userId]; if (url) return url; const flag = hasAvatarById[userId]; if (flag === undefined) { void loadUserFlags().then(() => { if (hasAvatarById[userId]) void fetchAvatar(userId); }); } else if (flag) { void fetchAvatar(userId); } return DEFAULT_USER_AVATAR; } /** بعد از تغییر عکس یک کاربر (مثلاً در تنظیمات تیم) کش را تازه کن. */ export function invalidateUserAvatar(userId: string) { const url = urlById[userId]; if (url) URL.revokeObjectURL(url); delete urlById[userId]; delete hasAvatarById[userId]; pending.delete(userId); usersLoad = null; }