MessengerWidget translate LanguageKey
This commit is contained in:
parent
a321e90a53
commit
662edaace6
2 changed files with 341 additions and 83 deletions
|
|
@ -19465,6 +19465,174 @@
|
|||
"key": "ListForms.ListForm.Workflow.UndefinedUser",
|
||||
"en": "Undefined",
|
||||
"tr": "Tanımsız"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Title",
|
||||
"en": "Messenger",
|
||||
"tr": "Messenger"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Connected",
|
||||
"en": "Connected",
|
||||
"tr": "Bağlı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Connecting",
|
||||
"en": "Connecting",
|
||||
"tr": "Bağlanıyor"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Minimize",
|
||||
"en": "Minimize",
|
||||
"tr": "Küçült"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Maximize",
|
||||
"en": "Maximize",
|
||||
"tr": "Büyüt"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.SearchPerson",
|
||||
"en": "Search person",
|
||||
"tr": "Kişi ara"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.MultiSelect",
|
||||
"en": "Multi-select",
|
||||
"tr": "Çoklu seçim"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.MultiSelectEnabled",
|
||||
"en": "Multi-select enabled",
|
||||
"tr": "Çoklu seçim açık"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Online",
|
||||
"en": "Online",
|
||||
"tr": "Online"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Offline",
|
||||
"en": "Offline",
|
||||
"tr": "Offline"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.PeopleSelected",
|
||||
"en": "people selected",
|
||||
"tr": "kişi seçildi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Chat",
|
||||
"en": "Chat",
|
||||
"tr": "Sohbet"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.GroupMessage",
|
||||
"en": "Group message",
|
||||
"tr": "Toplu mesaj"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.OfflineUserSelected",
|
||||
"en": "Offline user selected",
|
||||
"tr": "Offline kullanıcı seçili"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.SelectPersonToSendMessage",
|
||||
"en": "Select a person to send a message",
|
||||
"tr": "Mesaj göndermek için kişi seçin"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.NoMessagesYet",
|
||||
"en": "No messages yet",
|
||||
"tr": "Henüz mesaj yok"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Me",
|
||||
"en": "Me",
|
||||
"tr": "Ben"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.DeleteMessage",
|
||||
"en": "Delete message",
|
||||
"tr": "Mesajı sil"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.AddFile",
|
||||
"en": "Add file",
|
||||
"tr": "Dosya ekle"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.Emoji",
|
||||
"en": "Emoji",
|
||||
"tr": "Emoji"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.WriteMessage",
|
||||
"en": "Write a message",
|
||||
"tr": "Mesaj yazın"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.OfflineUsersCannotReceiveMessages",
|
||||
"en": "Messages cannot be sent to offline users",
|
||||
"tr": "Offline kullanıcılara mesaj gönderilemez"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.FileSizeLimitExceeded",
|
||||
"en": "File cannot exceed the 10 MB limit",
|
||||
"tr": "Dosya 10 MB sınırını aşamaz"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.FileUploadFailed",
|
||||
"en": "File could not be uploaded",
|
||||
"tr": "Dosya yüklenemedi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.OnlyOnlineUsersCanReceiveMessages",
|
||||
"en": "You can only send messages to online users",
|
||||
"tr": "Sadece online kullanıcılara mesaj gönderebilirsiniz"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.MessageSendFailed",
|
||||
"en": "Message could not be sent",
|
||||
"tr": "Mesaj gönderilemedi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.DeleteMessageConfirmation",
|
||||
"en": "Delete message?",
|
||||
"tr": "Mesaj silinsin mi?"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "MessengerWidget.MessageDeleteFailed",
|
||||
"en": "Message could not be deleted",
|
||||
"tr": "Mesaj silinemedi"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import {
|
|||
FaTrash,
|
||||
} from 'react-icons/fa'
|
||||
import { IoCheckmarkDone, IoChatbubbleEllipsesOutline, IoSend } from 'react-icons/io5'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
||||
const MAX_UPLOAD_SIZE = 10 * 1024 * 1024
|
||||
const CONTACT_REFRESH_INTERVAL = 30000
|
||||
|
|
@ -47,6 +48,7 @@ const MessengerWidget = () => {
|
|||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
const messageInputRef = useRef<HTMLTextAreaElement>(null)
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null)
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
const [contacts, setContacts] = useState<MessengerContactDto[]>([])
|
||||
|
|
@ -71,7 +73,9 @@ const MessengerWidget = () => {
|
|||
if (!auth.session.signedIn) return
|
||||
|
||||
const unsubscribeMessage = messengerSignalR.onMessage((message) => {
|
||||
setMessages((prev) => (prev.some((item) => item.id === message.id) ? prev : [...prev, message]))
|
||||
setMessages((prev) =>
|
||||
prev.some((item) => item.id === message.id) ? prev : [...prev, message],
|
||||
)
|
||||
if (message.senderId !== auth.user.id && (!open || !selectedIds.includes(message.senderId))) {
|
||||
setUnreadByContact((current) => ({
|
||||
...current,
|
||||
|
|
@ -161,16 +165,25 @@ const MessengerWidget = () => {
|
|||
return messages.filter((message) => {
|
||||
const isOwn = message.senderId === auth.user.id
|
||||
const participants = new Set([message.senderId, ...message.recipientIds])
|
||||
return selectedIds.some((id) => participants.has(id)) && (isOwn || selectedIds.includes(message.senderId))
|
||||
return (
|
||||
selectedIds.some((id) => participants.has(id)) &&
|
||||
(isOwn || selectedIds.includes(message.senderId))
|
||||
)
|
||||
})
|
||||
}, [auth.user.id, messages, selectedIds])
|
||||
|
||||
const toggleContact = (id: string) => {
|
||||
const contact = contacts.find((item) => item.id === id)
|
||||
if (!contact?.isOnline) {
|
||||
toast.push(<Notification title="Offline kullanıcılara mesaj gönderilemez" type="warning" />, {
|
||||
placement: 'top-end',
|
||||
})
|
||||
toast.push(
|
||||
<Notification
|
||||
title={translate('::MessengerWidget.OfflineUsersCannotReceiveMessages')}
|
||||
type="warning"
|
||||
/>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +200,9 @@ const MessengerWidget = () => {
|
|||
return
|
||||
}
|
||||
|
||||
setSelectedIds((prev) => (prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]))
|
||||
setSelectedIds((prev) =>
|
||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id],
|
||||
)
|
||||
}
|
||||
|
||||
const toggleMultiSelect = () => {
|
||||
|
|
@ -215,9 +230,15 @@ const MessengerWidget = () => {
|
|||
const nextFiles = Array.from(files)
|
||||
const tooLarge = nextFiles.find((file) => file.size > MAX_UPLOAD_SIZE)
|
||||
if (tooLarge) {
|
||||
toast.push(<Notification title="Dosya 10 MB sınırını aşamaz" type="warning" />, {
|
||||
placement: 'top-end',
|
||||
})
|
||||
toast.push(
|
||||
<Notification
|
||||
title={translate('::MessengerWidget.FileSizeLimitExceeded')}
|
||||
type="warning"
|
||||
/>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +249,10 @@ const MessengerWidget = () => {
|
|||
)
|
||||
setAttachments((prev) => [...prev, ...uploaded])
|
||||
} catch {
|
||||
toast.push(<Notification title="Dosya yüklenemedi" type="danger" />, { placement: 'top-end' })
|
||||
toast.push(
|
||||
<Notification title={translate('::MessengerWidget.FileUploadFailed')} type="danger" />,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
} finally {
|
||||
setUploading(false)
|
||||
if (fileInputRef.current) fileInputRef.current.value = ''
|
||||
|
|
@ -239,9 +263,15 @@ const MessengerWidget = () => {
|
|||
const trimmedText = text.trim()
|
||||
if (selectedIds.length === 0 || (!trimmedText && attachments.length === 0)) return
|
||||
if (!canSendToSelectedContacts) {
|
||||
toast.push(<Notification title="Sadece online kullanıcılara mesaj gönderebilirsiniz" type="warning" />, {
|
||||
placement: 'top-end',
|
||||
})
|
||||
toast.push(
|
||||
<Notification
|
||||
title={translate('::MessengerWidget.OnlyOnlineUsersCanReceiveMessages')}
|
||||
type="warning"
|
||||
/>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -258,17 +288,23 @@ const MessengerWidget = () => {
|
|||
messageInputRef.current?.focus()
|
||||
}, 0)
|
||||
} catch {
|
||||
toast.push(<Notification title="Mesaj gönderilemedi" type="danger" />, { placement: 'top-end' })
|
||||
toast.push(
|
||||
<Notification title={translate('::MessengerWidget.MessageSendFailed')} type="danger" />,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteMessage = async (messageId: string) => {
|
||||
if (!window.confirm('Mesaj silinsin mi?')) return
|
||||
if (!window.confirm(translate('::MessengerWidget.DeleteMessageConfirmation'))) return
|
||||
|
||||
try {
|
||||
await messengerSignalR.deleteMessage(messageId)
|
||||
} catch {
|
||||
toast.push(<Notification title="Mesaj silinemedi" type="danger" />, { placement: 'top-end' })
|
||||
toast.push(
|
||||
<Notification title={translate('::MessengerWidget.MessageDeleteFailed')} type="danger" />,
|
||||
{ placement: 'top-end' },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,19 +330,33 @@ const MessengerWidget = () => {
|
|||
>
|
||||
<div className="flex h-16 items-center justify-between border-b border-gray-200 px-4 dark:border-gray-700">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<Avatar size={36} shape="circle" src={auth.user.avatar || AVATAR_URL(auth.user.id, tenantId)} />
|
||||
<Avatar
|
||||
size={36}
|
||||
shape="circle"
|
||||
src={auth.user.avatar || AVATAR_URL(auth.user.id, tenantId)}
|
||||
/>
|
||||
<div className="min-w-0">
|
||||
<div className="truncate text-sm font-semibold text-gray-900 dark:text-gray-100">
|
||||
{auth.user.name || auth.user.userName || 'Messenger'}
|
||||
{auth.user.name || auth.user.userName || translate('::MessengerWidget.Title')}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-xs text-gray-500">
|
||||
<span className={`h-2 w-2 rounded-full ${connected ? 'bg-emerald-500' : 'bg-gray-400'}`} />
|
||||
{connected ? 'Bağlı' : 'Bağlanıyor'}
|
||||
<span
|
||||
className={`h-2 w-2 rounded-full ${connected ? 'bg-emerald-500' : 'bg-gray-400'}`}
|
||||
/>
|
||||
{connected
|
||||
? translate('::MessengerWidget.Connected')
|
||||
: translate('::MessengerWidget.Connecting')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1 sm:hidden">
|
||||
<Tooltip title={maximized ? 'Küçült' : 'Büyüt'}>
|
||||
<Tooltip
|
||||
title={
|
||||
maximized
|
||||
? translate('::MessengerWidget.Minimize')
|
||||
: translate('::MessengerWidget.Maximize')
|
||||
}
|
||||
>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="plain"
|
||||
|
|
@ -323,7 +373,7 @@ const MessengerWidget = () => {
|
|||
size="sm"
|
||||
value={filter}
|
||||
prefix={<FaSearch />}
|
||||
placeholder="Kişi ara"
|
||||
placeholder={translate('::MessengerWidget.SearchPerson')}
|
||||
onChange={(event) => setFilter(event.target.value)}
|
||||
/>
|
||||
<Button
|
||||
|
|
@ -332,7 +382,9 @@ const MessengerWidget = () => {
|
|||
block
|
||||
onClick={toggleMultiSelect}
|
||||
>
|
||||
{multiSelect ? 'Çoklu seçim açık' : 'Çoklu seçim'}
|
||||
{multiSelect
|
||||
? translate('::MessengerWidget.MultiSelectEnabled')
|
||||
: translate('::MessengerWidget.MultiSelect')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -354,9 +406,15 @@ const MessengerWidget = () => {
|
|||
: 'cursor-not-allowed opacity-60'
|
||||
}`}
|
||||
>
|
||||
<Avatar size={36} shape="circle" src={AVATAR_URL(contact.id, contact.tenantId || tenantId)} />
|
||||
<Avatar
|
||||
size={36}
|
||||
shape="circle"
|
||||
src={AVATAR_URL(contact.id, contact.tenantId || tenantId)}
|
||||
/>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="block truncate text-sm font-medium">{contact.fullName}</span>
|
||||
<span className="block truncate text-sm font-medium">
|
||||
{contact.fullName}
|
||||
</span>
|
||||
<span
|
||||
className={`mt-1 inline-flex items-center gap-1 text-xs font-medium ${
|
||||
contact.isOnline ? 'text-emerald-600' : 'text-red-500'
|
||||
|
|
@ -367,7 +425,9 @@ const MessengerWidget = () => {
|
|||
contact.isOnline ? 'bg-emerald-500' : 'bg-red-500'
|
||||
}`}
|
||||
/>
|
||||
{contact.isOnline ? 'Online' : 'Offline'}
|
||||
{contact.isOnline
|
||||
? translate('::MessengerWidget.Online')
|
||||
: translate('::MessengerWidget.Offline')}
|
||||
</span>
|
||||
</span>
|
||||
{contactUnread > 0 && (
|
||||
|
|
@ -375,7 +435,9 @@ const MessengerWidget = () => {
|
|||
{contactUnread > 99 ? '99+' : contactUnread}
|
||||
</span>
|
||||
)}
|
||||
{active && contactUnread === 0 && <IoCheckmarkDone className="shrink-0 text-lg" />}
|
||||
{active && contactUnread === 0 && (
|
||||
<IoCheckmarkDone className="shrink-0 text-lg" />
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
|
|
@ -400,7 +462,10 @@ const MessengerWidget = () => {
|
|||
<Avatar
|
||||
size={36}
|
||||
shape="circle"
|
||||
src={AVATAR_URL(selectedContacts[0].id, selectedContacts[0].tenantId || tenantId)}
|
||||
src={AVATAR_URL(
|
||||
selectedContacts[0].id,
|
||||
selectedContacts[0].tenantId || tenantId,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{selectedContacts.length > 1 && (
|
||||
|
|
@ -413,24 +478,30 @@ const MessengerWidget = () => {
|
|||
{selectedContacts.length === 1
|
||||
? selectedContacts[0].fullName
|
||||
: selectedContacts.length > 1
|
||||
? `${selectedContacts.length} kişi seçildi`
|
||||
: 'Sohbet'}
|
||||
? `${selectedContacts.length} ${translate('::MessengerWidget.PeopleSelected')}`
|
||||
: translate('::MessengerWidget.Chat')}
|
||||
</div>
|
||||
<div className="truncate text-xs text-gray-500">
|
||||
{selectedContacts.length === 1
|
||||
? `${selectedContacts[0].isOnline ? 'Online' : 'Offline'} - ${
|
||||
? `${selectedContacts[0].isOnline ? translate('::MessengerWidget.Online') : translate('::MessengerWidget.Offline')} - ${
|
||||
selectedContacts[0].email || selectedContacts[0].userName
|
||||
}`
|
||||
: selectedContacts.length > 1
|
||||
? canSendToSelectedContacts
|
||||
? 'Toplu mesaj'
|
||||
: 'Offline kullanici secili'
|
||||
: 'Mesaj göndermek için kişi seçin'}
|
||||
? translate('::MessengerWidget.GroupMessage')
|
||||
: translate('::MessengerWidget.OfflineUserSelected')
|
||||
: translate('::MessengerWidget.SelectPersonToSendMessage')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
<Tooltip title={maximized ? 'Küçült' : 'Büyüt'}>
|
||||
<Tooltip
|
||||
title={
|
||||
maximized
|
||||
? translate('::MessengerWidget.Minimize')
|
||||
: translate('::MessengerWidget.Maximize')
|
||||
}
|
||||
>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="plain"
|
||||
|
|
@ -445,7 +516,7 @@ const MessengerWidget = () => {
|
|||
<div className="flex-1 overflow-y-auto bg-white px-4 py-3 dark:bg-gray-800">
|
||||
{visibleMessages.length === 0 && (
|
||||
<div className="flex h-full items-center justify-center text-sm text-gray-400">
|
||||
Henüz mesaj yok
|
||||
{translate('::MessengerWidget.NoMessagesYet')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -453,8 +524,13 @@ const MessengerWidget = () => {
|
|||
const own = message.senderId === auth.user.id
|
||||
const deletable = canDeleteMessage(message, auth.user.id)
|
||||
return (
|
||||
<div key={message.id} className={`mb-3 flex ${own ? 'justify-end' : 'justify-start'}`}>
|
||||
<div className={`group flex max-w-[76%] items-start gap-1.5 ${own ? 'flex-row-reverse' : ''}`}>
|
||||
<div
|
||||
key={message.id}
|
||||
className={`mb-3 flex ${own ? 'justify-end' : 'justify-start'}`}
|
||||
>
|
||||
<div
|
||||
className={`group flex max-w-[76%] items-start gap-1.5 ${own ? 'flex-row-reverse' : ''}`}
|
||||
>
|
||||
<div
|
||||
className={`rounded-lg px-3 py-2 shadow-sm ${
|
||||
own
|
||||
|
|
@ -462,51 +538,63 @@ const MessengerWidget = () => {
|
|||
: 'bg-gray-100 text-gray-900 dark:bg-gray-700 dark:text-gray-100'
|
||||
}`}
|
||||
>
|
||||
<div className="mb-1 flex items-center gap-1.5 text-xs font-semibold">
|
||||
<Avatar
|
||||
size={20}
|
||||
shape="circle"
|
||||
src={
|
||||
own
|
||||
? auth.user.avatar || AVATAR_URL(auth.user.id, tenantId)
|
||||
: AVATAR_URL(message.senderId, message.tenantId || tenantId)
|
||||
}
|
||||
/>
|
||||
<span className="max-w-[160px] truncate">
|
||||
{own ? auth.user.name || auth.user.userName || 'Ben' : message.senderName}
|
||||
</span>
|
||||
</div>
|
||||
{message.text && <div className="whitespace-pre-wrap text-sm leading-5">{message.text}</div>}
|
||||
{message.attachments.length > 0 && (
|
||||
<div className="mt-2 space-y-1">
|
||||
{message.attachments.map((file) => (
|
||||
<a
|
||||
key={file.savedFileName}
|
||||
href={file.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`block rounded-md px-2 py-1 text-xs ${
|
||||
own ? 'bg-emerald-700 text-white' : 'bg-white text-gray-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
}`}
|
||||
>
|
||||
<span className="block truncate">{file.fileName}</span>
|
||||
<span className="opacity-75">{formatFileSize(file.fileSize)}</span>
|
||||
</a>
|
||||
))}
|
||||
<div className="mb-1 flex items-center gap-1.5 text-xs font-semibold">
|
||||
<Avatar
|
||||
size={20}
|
||||
shape="circle"
|
||||
src={
|
||||
own
|
||||
? auth.user.avatar || AVATAR_URL(auth.user.id, tenantId)
|
||||
: AVATAR_URL(message.senderId, message.tenantId || tenantId)
|
||||
}
|
||||
/>
|
||||
<span className="max-w-[160px] truncate">
|
||||
{own
|
||||
? auth.user.name ||
|
||||
auth.user.userName ||
|
||||
translate('::MessengerWidget.Me')
|
||||
: message.senderName}
|
||||
</span>
|
||||
</div>
|
||||
{message.text && (
|
||||
<div className="whitespace-pre-wrap text-sm leading-5">
|
||||
{message.text}
|
||||
</div>
|
||||
)}
|
||||
{message.attachments.length > 0 && (
|
||||
<div className="mt-2 space-y-1">
|
||||
{message.attachments.map((file) => (
|
||||
<a
|
||||
key={file.savedFileName}
|
||||
href={file.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`block rounded-md px-2 py-1 text-xs ${
|
||||
own
|
||||
? 'bg-emerald-700 text-white'
|
||||
: 'bg-white text-gray-700 dark:bg-gray-800 dark:text-gray-100'
|
||||
}`}
|
||||
>
|
||||
<span className="block truncate">{file.fileName}</span>
|
||||
<span className="opacity-75">
|
||||
{formatFileSize(file.fileSize)}
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`mt-1 flex items-center gap-2 text-[11px] ${
|
||||
own ? 'justify-end text-emerald-100' : 'justify-start text-gray-500'
|
||||
}`}
|
||||
>
|
||||
<span>{dayjs(message.sentAt).format('HH:mm')}</span>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`mt-1 flex items-center gap-2 text-[11px] ${
|
||||
own ? 'justify-end text-emerald-100' : 'justify-start text-gray-500'
|
||||
}`}
|
||||
>
|
||||
<span>{dayjs(message.sentAt).format('HH:mm')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{own && deletable && (
|
||||
<button
|
||||
type="button"
|
||||
title="Mesaji sil"
|
||||
title={translate('::MessengerWidget.DeleteMessage')}
|
||||
className="mt-1 flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-[10px] text-gray-400 opacity-0 transition hover:bg-red-500 hover:text-white group-hover:opacity-100 focus:opacity-100"
|
||||
onClick={() => deleteMessage(message.id)}
|
||||
>
|
||||
|
|
@ -562,7 +650,7 @@ const MessengerWidget = () => {
|
|||
className="hidden"
|
||||
onChange={(event) => handleFiles(event.target.files)}
|
||||
/>
|
||||
<Tooltip title="Dosya ekle">
|
||||
<Tooltip title={translate('::MessengerWidget.AddFile')}>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
|
|
@ -574,7 +662,7 @@ const MessengerWidget = () => {
|
|||
onClick={() => fileInputRef.current?.click()}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="Emoji">
|
||||
<Tooltip title={translate('::MessengerWidget.Emoji')}>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
|
|
@ -587,7 +675,7 @@ const MessengerWidget = () => {
|
|||
<textarea
|
||||
ref={messageInputRef}
|
||||
value={text}
|
||||
placeholder="Mesaj yazın"
|
||||
placeholder={translate('::MessengerWidget.WriteMessage')}
|
||||
rows={1}
|
||||
autoFocus
|
||||
disabled={!canSendToSelectedContacts}
|
||||
|
|
@ -606,7 +694,9 @@ const MessengerWidget = () => {
|
|||
variant="solid"
|
||||
icon={<IoSend />}
|
||||
className="shrink-0"
|
||||
disabled={!canSendToSelectedContacts || (!text.trim() && attachments.length === 0)}
|
||||
disabled={
|
||||
!canSendToSelectedContacts || (!text.trim() && attachments.length === 0)
|
||||
}
|
||||
onClick={sendMessage}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -617,7 +707,7 @@ const MessengerWidget = () => {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<Tooltip title="Messenger">
|
||||
<Tooltip title={translate('::MessengerWidget.Title')}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => (open ? closeWidget() : setOpen(true))}
|
||||
|
|
|
|||
Loading…
Reference in a new issue