Show messages of deleted users

This commit is contained in:
MartinBraquet
2026-02-11 13:16:28 +01:00
parent 7598f32c56
commit 6ad3d3051f
4 changed files with 72 additions and 38 deletions

View File

@@ -314,6 +314,8 @@
"messages.toast.muting_forever.success": "Benachrichtigungen dauerhaft stummgeschaltet",
"messages.toast.send_failed": "Senden der Nachricht fehlgeschlagen. Bitte versuchen Sie es später erneut oder kontaktieren Sie den Support, wenn das Problem weiterhin besteht.",
"messages.you_prefix": "Sie: ",
"messages.cannot_message_deleted": "Sie können ihnen keine Nachricht senden, da sie ihr Konto gelöscht haben",
"messages.deleted_user": "Gelöschter Benutzer",
"multi-checkbox.enter_value": "Bitte geben Sie einen Wert ein.",
"multi-checkbox.could_not_add": "Option konnte nicht hinzugefügt werden.",
"multi-checkbox.add_failed": "Hinzufügen der Option fehlgeschlagen.",

View File

@@ -314,6 +314,8 @@
"messages.toast.muting_forever.success": "Notifs coupées définitivement",
"messages.toast.send_failed": "Échec de l'envoi du message. Veuillez réessayer plus tard ou contacter le support si le problème persiste.",
"messages.you_prefix": "Vous : ",
"messages.cannot_message_deleted": "Vous ne pouvez pas leur envoyer de message car ils ont supprimé leur compte",
"messages.deleted_user": "Utilisateur supprimé",
"multi-checkbox.enter_value": "Veuillez saisir une valeur.",
"multi-checkbox.could_not_add": "Impossible d'ajouter l'option.",
"multi-checkbox.add_failed": "Échec de l'ajout de l'option.",

View File

@@ -1,6 +1,6 @@
import {PageBase} from 'web/components/page-base'
import {useRouter} from 'next/router'
import {usePrivateMessages, useSortedPrivateMessageMemberships,} from 'web/hooks/use-private-messages'
import {usePrivateMessages, useSortedPrivateMessageMemberships} from 'web/hooks/use-private-messages'
import {Col} from 'web/components/layout/col'
import {User} from 'common/user'
import {useCallback, useEffect, useState} from 'react'
@@ -19,6 +19,7 @@ import {Row} from 'web/components/layout/row'
import clsx from 'clsx'
import {useRedirectIfSignedOut} from 'web/hooks/use-redirect-if-signed-out'
import {MultipleOrSingleAvatars} from 'web/components/multiple-or-single-avatars'
import {Avatar} from 'web/components/widgets/avatar'
import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
import {BannedBadge, UserAvatarAndBadge,} from 'web/components/widgets/user-link'
import DropdownMenu from 'web/components/comments/dropdown-menu'
@@ -69,6 +70,7 @@ export function PrivateMessagesContent(props: {
useRedirectIfSignedOut()
const {channelId, user} = props
const t = useT()
const channelMembership = useSortedPrivateMessageMemberships(
user.id,
1,
@@ -77,14 +79,20 @@ export function PrivateMessagesContent(props: {
const {channels, memberIdsByChannelId} = channelMembership
const thisChannel = channels?.find((c) => c.channel_id == channelId)
const loaded = channels !== undefined && channelId
const memberIds = thisChannel
const memberIds = (thisChannel
? memberIdsByChannelId?.[thisChannel.channel_id]
: undefined
: undefined) ?? []
return (
<>
{user && loaded && thisChannel && memberIds ? (
<PrivateChat channel={thisChannel} user={user} memberIds={memberIds}/>
{user && loaded ? (
thisChannel ? (
<PrivateChat channel={thisChannel} user={user} memberIds={memberIds}/>
) : (
<div className="flex h-[50vh] flex-col items-center justify-center mx-4 font-bold text-2xl">
{t('', 'You do not have access to this conversation.')}
</div>
)
) : (
<CompassLoadingIndicator/>
)}
@@ -103,6 +111,8 @@ export const PrivateChat = (props: {
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
const isMobile = useIsMobile()
const noOtherUser = memberIds.length === 0
const totalMessagesToLoad = 100
const {messages: realtimeMessages, setMessages, fetchMessages} = usePrivateMessages(
channelId,
@@ -246,16 +256,20 @@ export const PrivateChat = (props: {
}
>
<BackButton className="self-stretch"/>
<MultipleOrSingleAvatars
size="sm"
spacing={0.5}
startLeft={1}
avatars={members ?? []}
onClick={() => setShowUsers(true)}
/>
{members && (
{members && members.length > 0 ? (
<MultipleOrSingleAvatars
size="sm"
spacing={0.5}
startLeft={1}
avatars={members}
onClick={() => setShowUsers(true)}
/>
) : (
<Avatar size="sm" username="?" noLink/>
)}
{members && members.length > 0 ? (
<span
className={'ml-1 cursor-pointer hover:underline'}
className={clsx('ml-1 cursor-pointer hover:underline', noOtherUser && 'italic')}
onClick={() =>
members.length === 1
? router.push(`/${members[0].username}`)
@@ -263,11 +277,13 @@ export const PrivateChat = (props: {
}
>
{members
.map((user) => user.name.split(' ')[0].trim())
.map((user) => (user.name ? user.name.split(' ')[0].trim() : t('messages.deleted_user', 'Deleted user')))
.slice(0, 2)
.join(', ')}
{members.length > 2 && ` & ${members.length - 2} more`}
</span>
) : (
<span className={'ml-1 italic'}>{t('messages.deleted_user', 'Deleted user')}</span>
)}
{members?.length == 1 && members[0].isBannedFromPosting && (
@@ -419,16 +435,24 @@ export const PrivateChat = (props: {
</div>
</div>
</Col>
<CommentInputTextArea
editor={editor}
user={user}
submit={submitMessage}
isSubmitting={isSubmitting}
submitOnEnter={!isMobile}
replyTo={replyToUserInfo}
isEditing={!!editingMessage}
cancelEditing={cancelEditing}
/>
{noOtherUser ? (
<div className="border-ink-200 p-4 text-center">
<span className="text-ink-600">
{t('messages.cannot_message_deleted', "You can't text them as they deleted their account")}
</span>
</div>
) : (
<CommentInputTextArea
editor={editor}
user={user}
submit={submitMessage}
isSubmitting={isSubmitting}
submitOnEnter={!isMobile}
replyTo={replyToUserInfo}
isEditing={!!editingMessage}
cancelEditing={cancelEditing}
/>
)}
</Col>
)
}

View File

@@ -17,6 +17,7 @@ import {useUser} from 'web/hooks/use-user'
import {useUsersInStore} from 'web/hooks/use-user-supabase'
import {useRedirectIfSignedOut} from 'web/hooks/use-redirect-if-signed-out'
import {MultipleOrSingleAvatars} from 'web/components/multiple-or-single-avatars'
import {Avatar} from 'web/components/widgets/avatar'
import {BannedBadge} from 'web/components/widgets/user-link'
import {PrivateMessageChannel} from 'common/supabase/private-messages'
import {SEO} from "web/components/SEO";
@@ -66,8 +67,7 @@ export function MessagesContent(props: { currentUser: User }) {
{channels?.map((channel) => {
const userIds = memberIdsByChannelId?.[channel.channel_id]?.map(
(m) => m
)
if (!userIds) return null
) || []
return (
<MessageChannelRow
key={channel.channel_id}
@@ -100,26 +100,30 @@ export const MessageChannelRow = (props: {
const isBanned = otherUsers?.length == 1 && otherUsers[0].isBannedFromPosting
return (
<Row className={'items-center gap-3 rounded-md'}>
<MultipleOrSingleAvatars
size="md"
spacing={numOthers === 2 ? 0.3 : 0.15}
startLeft={numOthers === 2 ? 2.2 : 1.2}
avatars={otherUsers ?? []}
className={numOthers > 1 ? '-ml-2' : ''}
/>
<Row className={'items-center gap-3 rounded-md hover:bg-canvas-100 p-2'}>
{otherUsers && otherUsers.length > 0 ? (
<MultipleOrSingleAvatars
size="md"
spacing={numOthers === 2 ? 0.3 : 0.15}
startLeft={numOthers === 2 ? 2.2 : 1.2}
avatars={otherUsers}
className={numOthers > 1 ? '-ml-2' : ''}
/>
) : (
<Avatar size="md" username="?" noLink/>
)}
<Link
className="hover:bg-canvas-0 rounded p-2 transition-colors w-full"
className="rounded w-full"
key={channelId}
href={'/messages/' + channelId}
>
<Col className={''}>
<Row className={'items-center justify-between'}>
<span className={'font-semibold'}>
{otherUsers && (
{otherUsers && otherUsers.length > 0 ? (
<span>
{otherUsers
.map((user) => user.name.split(' ')[0].trim())
.map((user) => (user.name ? user.name.split(' ')[0].trim() : t('messages.deleted_user', 'Deleted user')))
.slice(0, 2)
.join(', ')}
{otherUsers.length > 2 && (
@@ -129,6 +133,8 @@ export const MessageChannelRow = (props: {
</>
)}
</span>
) : (
<span className="italic">{t('messages.deleted_user', 'Deleted user')}</span>
)}
{isBanned && <BannedBadge/>}
</span>