фикс <был недавно>
This commit is contained in:
@@ -13,7 +13,7 @@ import Avatar from '../../../../core/presentation/components/ui/Avatar';
|
||||
import type { Chat } from '../../../../core/domain/types';
|
||||
import { UserApi } from '../../../users/infrastructure/userApi';
|
||||
|
||||
const userStatusCache = new Map<string, { emoji?: string | null; text?: string | null }>();
|
||||
const userStatusCache = new Map<string, { emoji?: string | null; text?: string | null; isInvisible?: boolean }>();
|
||||
|
||||
interface ChatListItemProps {
|
||||
chat: Chat;
|
||||
@@ -27,7 +27,7 @@ function ChatListItem({ chat, isActive }: ChatListItemProps) {
|
||||
|
||||
const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number } | null>(null);
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [otherUserStatus, setOtherUserStatus] = useState<{ emoji?: string | null; text?: string | null } | null>(null);
|
||||
const [otherUserStatus, setOtherUserStatus] = useState<{ emoji?: string | null; text?: string | null; isInvisible?: boolean } | null>(null);
|
||||
const ctxRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const myMember = chat.members.find((m) => m.user.id === user?.id);
|
||||
@@ -49,7 +49,7 @@ function ChatListItem({ chat, isActive }: ChatListItemProps) {
|
||||
? otherMember?.user.avatarUrl || otherMember?.user.avatar || null
|
||||
: chat.avatarUrl || chat.avatar || null;
|
||||
|
||||
const isOnline = chat.type === 'personal' && !user?.isInvisible && !!otherMember?.user.isOnline;
|
||||
const isOnline = chat.type === 'personal' && !user?.isInvisible && !otherUserStatus?.isInvisible && !!otherMember?.user.isOnline;
|
||||
|
||||
// Check if someone is typing in this chat
|
||||
const typingInChat = typingUsers.filter((t) => t.chatId === chat.id && t.userId !== user?.id);
|
||||
@@ -108,7 +108,7 @@ function ChatListItem({ chat, isActive }: ChatListItemProps) {
|
||||
UserApi.getUser(otherId)
|
||||
.then((profile) => {
|
||||
if (cancelled) return;
|
||||
const status = { emoji: profile.statusEmoji, text: profile.statusText };
|
||||
const status = { emoji: profile.statusEmoji, text: profile.statusText, isInvisible: !!profile.isInvisible };
|
||||
userStatusCache.set(otherId, status);
|
||||
setOtherUserStatus(status);
|
||||
})
|
||||
|
||||
@@ -24,6 +24,7 @@ import { useChatStore } from '../../application/chatStore';
|
||||
import { httpClient } from '../../../../core/infrastructure/httpClient';
|
||||
import { useAuthStore } from '../../../auth/application/authStore';
|
||||
import { ChatApi } from '../../infrastructure/chatApi';
|
||||
import { UserApi } from '../../../users/infrastructure/userApi';
|
||||
import { getSocket } from '../../../../core/infrastructure/socket';
|
||||
import { isChatMuted, toggleMuteChat } from '../../../../core/utils/sounds';
|
||||
import { useLang } from '../../../../core/infrastructure/i18n';
|
||||
@@ -75,6 +76,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
|
||||
const [confirmAction, setConfirmAction] = useState<{ message: string; action: () => void } | null>(null);
|
||||
const [scrollReady, setScrollReady] = useState(false);
|
||||
const [activeGroupCallParticipants, setActiveGroupCallParticipants] = useState<string[]>([]);
|
||||
const [otherUserInvisible, setOtherUserInvisible] = useState(false);
|
||||
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -182,6 +184,31 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
|
||||
: chat?.avatarUrl || chat?.avatar || null;
|
||||
const isOnline = chat?.type === 'personal' && otherMember?.user.isOnline;
|
||||
const privacyExchangeMode = !!user?.isInvisible;
|
||||
const shouldMaskOtherUserPresence = privacyExchangeMode || otherUserInvisible;
|
||||
useEffect(() => {
|
||||
if (chat?.type !== 'personal' || !otherMember?.user.id) {
|
||||
setOtherUserInvisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
UserApi.getUser(otherMember.user.id)
|
||||
.then((profile) => {
|
||||
if (!cancelled) {
|
||||
setOtherUserInvisible(!!profile.isInvisible);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setOtherUserInvisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [chat?.type, otherMember?.user.id]);
|
||||
|
||||
|
||||
const typingInChat = typingUsers.filter((t) => t.chatId === activeChat && t.userId !== user?.id);
|
||||
|
||||
@@ -846,7 +873,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
|
||||
src={chatAvatar}
|
||||
name={chatName}
|
||||
size="md"
|
||||
online={isOnline ? true : undefined}
|
||||
online={!shouldMaskOtherUserPresence && isOnline ? true : undefined}
|
||||
className="avatar-knot-container group-hover:border-primary/30"
|
||||
/>
|
||||
)}
|
||||
@@ -860,7 +887,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
|
||||
? <span className="text-primary font-black animate-pulse">{t('typing')}</span>
|
||||
: isOnline
|
||||
? <span className="text-success">{t('online')}</span>
|
||||
: chat.type === 'personal' && privacyExchangeMode
|
||||
: chat.type === 'personal' && shouldMaskOtherUserPresence
|
||||
? t('wasRecently')
|
||||
: chat.type === 'personal' && otherMember?.user.lastSeen
|
||||
? `${formatLastSeen(otherMember.user.lastSeen, lang)}`
|
||||
|
||||
Reference in New Issue
Block a user