@pubuduth-aplicy/chat-ui 2.1.58 → 2.1.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -11,8 +11,8 @@ import { getApiClient } from "../../lib/api/apiClient";
|
|
|
11
11
|
import { MessageStatus } from "../../types/type";
|
|
12
12
|
import { Path } from "../../lib/api/endpoint";
|
|
13
13
|
const MAX_FILE_SIZE_MB = 5; // 5MB max file size
|
|
14
|
-
const MAX_FILE_COUNT = 5;
|
|
15
|
-
const ACCEPTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp','video/mp4', 'video/webm', 'video/ogg'];
|
|
14
|
+
const MAX_FILE_COUNT = 5;
|
|
15
|
+
const ACCEPTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'video/mp4', 'video/webm', 'video/ogg'];
|
|
16
16
|
const ACCEPTED_VIDEO_TYPES = ['video/mp4', 'video/webm', 'video/ogg'];
|
|
17
17
|
const ACCEPTED_DOCUMENT_TYPES = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'text/plain'];
|
|
18
18
|
|
|
@@ -28,14 +28,14 @@ const MessageInput = () => {
|
|
|
28
28
|
const apiClient = getApiClient();
|
|
29
29
|
const { socket } = useChatContext();
|
|
30
30
|
const { userId } = useChatContext();
|
|
31
|
-
const { selectedConversation,setMessages } = useChatUIStore();
|
|
32
|
-
const [message, setMessage] = useState("");
|
|
33
|
-
const [message1, setMessage1] = useState("");
|
|
34
|
-
const mutation = useMessageMutation();
|
|
31
|
+
const { selectedConversation, setMessages } = useChatUIStore();
|
|
32
|
+
const [message, setMessage] = useState("");
|
|
33
|
+
const [message1, setMessage1] = useState("");
|
|
34
|
+
const mutation = useMessageMutation();
|
|
35
35
|
const [typingUser, setTypingUser] = useState<string | null>(null);
|
|
36
36
|
const [isSending, setIsSending] = useState(false);
|
|
37
37
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38
|
-
const [isTyping, setIsTyping] = useState(false);
|
|
38
|
+
const [isTyping, setIsTyping] = useState(false);
|
|
39
39
|
const [attachments, setAttachments] = useState<Attachment[]>([]);
|
|
40
40
|
const [showAttachmentOptions, setShowAttachmentOptions] = useState(false);
|
|
41
41
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
@@ -85,37 +85,37 @@ const MessageInput = () => {
|
|
|
85
85
|
if (emailRegex.test(text)) {
|
|
86
86
|
return "Email addresses are not allowed.";
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
// Check for phone number (very basic)
|
|
90
90
|
const phoneRegex = /(\+?\d{1,4}[\s-]?)?(\(?\d{3}\)?[\s-]?)?\d{3}[\s-]?\d{4}/;
|
|
91
91
|
if (phoneRegex.test(text)) {
|
|
92
92
|
return "Phone numbers are not allowed.";
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
// // Check for bad words
|
|
96
96
|
// for (const word of badWords) {
|
|
97
97
|
// if (text.toLowerCase().includes(word)) {
|
|
98
98
|
// return "Inappropriate language is not allowed.";
|
|
99
99
|
// }
|
|
100
100
|
// }
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
return null; // No errors
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
106
106
|
const newValue = e.target.value;
|
|
107
107
|
const validationError = validateInput(newValue);
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
if (validationError) {
|
|
110
110
|
setInputError(validationError);
|
|
111
111
|
} else {
|
|
112
112
|
setInputError(null);
|
|
113
113
|
setMessage(newValue);
|
|
114
114
|
setMessage1(newValue);
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
|
|
120
120
|
useEffect(() => {
|
|
121
121
|
if (!socket || !selectedConversation?._id) return;
|
|
@@ -148,15 +148,15 @@ const MessageInput = () => {
|
|
|
148
148
|
return null;
|
|
149
149
|
};
|
|
150
150
|
|
|
151
|
-
const uploadToS3 = async (file: File, onProgress?:(progress:number)=> void): Promise<{ url: string, name: string, size: number, type: FileType }> => {
|
|
151
|
+
const uploadToS3 = async (file: File, onProgress?: (progress: number) => void): Promise<{ url: string, name: string, size: number, type: FileType }> => {
|
|
152
152
|
const response = await apiClient.post(`${Path.preSignUrl}`, {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
fileName: file.name,
|
|
154
|
+
fileType: file.type,
|
|
155
|
+
}
|
|
156
156
|
);
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
const { signedUrl, fileUrl } = await response.data;
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
// const uploadResponse = await fetch(signedUrl, {
|
|
161
161
|
// method: 'PUT',
|
|
162
162
|
// body: file,
|
|
@@ -194,11 +194,11 @@ const MessageInput = () => {
|
|
|
194
194
|
xhr.onerror = () => reject(new Error('Upload failed'));
|
|
195
195
|
xhr.send(file);
|
|
196
196
|
});
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
// if (!uploadResponse.ok) {
|
|
199
199
|
// throw new Error('Upload failed');
|
|
200
200
|
// }
|
|
201
|
-
|
|
201
|
+
|
|
202
202
|
// return {
|
|
203
203
|
// url: fileUrl,
|
|
204
204
|
// name: file.name,
|
|
@@ -241,11 +241,11 @@ const MessageInput = () => {
|
|
|
241
241
|
try {
|
|
242
242
|
|
|
243
243
|
const uploadedFiles = await Promise.all(
|
|
244
|
-
attachmentsRef.current.map(async (attachment,index) => {
|
|
244
|
+
attachmentsRef.current.map(async (attachment, index) => {
|
|
245
245
|
try {
|
|
246
|
-
const result = await uploadToS3(attachment.file,(progress)=>{
|
|
247
|
-
setMessages(prev => prev.map(msg =>{
|
|
248
|
-
if(msg._id === tempId){
|
|
246
|
+
const result = await uploadToS3(attachment.file, (progress) => {
|
|
247
|
+
setMessages(prev => prev.map(msg => {
|
|
248
|
+
if (msg._id === tempId) {
|
|
249
249
|
const updatedMedia = [...msg.media!];
|
|
250
250
|
updatedMedia[index] = {
|
|
251
251
|
...updatedMedia[index],
|
|
@@ -270,7 +270,7 @@ const MessageInput = () => {
|
|
|
270
270
|
} catch (error) {
|
|
271
271
|
console.error(`Error uploading file ${attachment.file.name}:`, error);
|
|
272
272
|
setMessages(prev => prev.map(msg => {
|
|
273
|
-
if(msg._id === tempId){
|
|
273
|
+
if (msg._id === tempId) {
|
|
274
274
|
const updatedMedia = [...msg.media!];
|
|
275
275
|
updatedMedia[index] = {
|
|
276
276
|
...updatedMedia[index],
|
|
@@ -287,8 +287,8 @@ const MessageInput = () => {
|
|
|
287
287
|
}
|
|
288
288
|
})
|
|
289
289
|
);
|
|
290
|
-
|
|
291
|
-
|
|
290
|
+
|
|
291
|
+
|
|
292
292
|
const successfulUploads = uploadedFiles.filter(file => file !== null);
|
|
293
293
|
|
|
294
294
|
console.log("📤 Sending message:", successfulUploads);
|
|
@@ -300,33 +300,34 @@ const MessageInput = () => {
|
|
|
300
300
|
}, {
|
|
301
301
|
onSuccess: (data) => {
|
|
302
302
|
console.log('Response from sendMessage:', data);
|
|
303
|
-
|
|
304
|
-
socket.emit("sendMessage", {
|
|
305
|
-
chatId: selectedConversation?._id,
|
|
306
|
-
message: message1,
|
|
307
|
-
messageId: data[1]._id,
|
|
308
|
-
attachments: successfulUploads,
|
|
309
|
-
senderId: userId,
|
|
310
|
-
receiverId: selectedConversation?.participantDetails._id,
|
|
311
|
-
});
|
|
312
303
|
setMessages(prev => {
|
|
313
304
|
console.log("Removing optimistic message:", prev);
|
|
314
|
-
|
|
305
|
+
|
|
315
306
|
// Definitely remove the optimistic message
|
|
316
307
|
const filtered = prev.filter(msg => msg._id !== tempMessageId);
|
|
317
308
|
// Add the real message from server
|
|
318
309
|
console.log("Adding real message:", filtered);
|
|
319
|
-
|
|
310
|
+
|
|
320
311
|
return [...filtered, {
|
|
321
312
|
...data[1],
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
isUploading: false,
|
|
314
|
+
isOptimistic: false
|
|
315
|
+
}
|
|
316
|
+
];
|
|
317
|
+
});
|
|
318
|
+
socket.emit("sendMessage", {
|
|
319
|
+
chatId: selectedConversation?._id,
|
|
320
|
+
message: message1,
|
|
321
|
+
messageId: data[1]._id,
|
|
322
|
+
attachments: successfulUploads,
|
|
323
|
+
senderId: userId,
|
|
324
|
+
receiverId: selectedConversation?.participantDetails._id,
|
|
325
325
|
});
|
|
326
|
+
|
|
326
327
|
},
|
|
327
328
|
onError: (error) => {
|
|
328
329
|
console.error("❌ Error in sending message:", error);
|
|
329
|
-
setMessages(prev => prev.map(msg =>
|
|
330
|
+
setMessages(prev => prev.map(msg =>
|
|
330
331
|
msg._id === tempId ? { ...msg, status: 'failed' } : msg
|
|
331
332
|
));
|
|
332
333
|
},
|
|
@@ -334,7 +335,7 @@ const MessageInput = () => {
|
|
|
334
335
|
|
|
335
336
|
} catch (error) {
|
|
336
337
|
console.error("❌ Error sending message:", error);
|
|
337
|
-
setMessages(prev => prev.map(msg =>
|
|
338
|
+
setMessages(prev => prev.map(msg =>
|
|
338
339
|
msg._id === tempId ? { ...msg, status: 'failed' } : msg
|
|
339
340
|
));
|
|
340
341
|
} finally {
|
|
@@ -398,7 +399,7 @@ const MessageInput = () => {
|
|
|
398
399
|
// Calculate total size of new files
|
|
399
400
|
const newFilesSize = Array.from(files).reduce((total, file) => total + file.size, 0);
|
|
400
401
|
const currentAttachmentsSize = attachments.reduce((total, att) => total + att.file.size, 0);
|
|
401
|
-
|
|
402
|
+
|
|
402
403
|
// Check if total size would exceed the limit
|
|
403
404
|
if (currentAttachmentsSize + newFilesSize > MAX_FILE_SIZE_MB * 1024 * 1024) {
|
|
404
405
|
alert(`Total file size cannot exceed ${MAX_FILE_SIZE_MB}MB`);
|
|
@@ -421,7 +422,7 @@ const MessageInput = () => {
|
|
|
421
422
|
continue;
|
|
422
423
|
}
|
|
423
424
|
|
|
424
|
-
const previewUrl = fileType === 'document'
|
|
425
|
+
const previewUrl = fileType === 'document'
|
|
425
426
|
? URL.createObjectURL(new Blob([''], { type: 'application/pdf' })) // Placeholder for documents
|
|
426
427
|
: URL.createObjectURL(file);
|
|
427
428
|
|
|
@@ -437,7 +438,7 @@ const MessageInput = () => {
|
|
|
437
438
|
fileInputRef.current.value = '';
|
|
438
439
|
}
|
|
439
440
|
};
|
|
440
|
-
|
|
441
|
+
|
|
441
442
|
const scrollAttachments = (direction: 'left' | 'right') => {
|
|
442
443
|
if (attachmentsContainerRef.current) {
|
|
443
444
|
const scrollAmount = direction === 'right' ? 200 : -200;
|
|
@@ -459,148 +460,149 @@ const MessageInput = () => {
|
|
|
459
460
|
|
|
460
461
|
return (
|
|
461
462
|
<div className="message-input-container">
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
<button
|
|
466
|
-
className="scroll-button left"
|
|
467
|
-
onClick={() => scrollAttachments('left')}
|
|
468
|
-
disabled={attachments.length <= 3}
|
|
469
|
-
>
|
|
470
|
-
<
|
|
471
|
-
</button>
|
|
472
|
-
|
|
473
|
-
<div className="attachments-preview" ref={attachmentsContainerRef}>
|
|
474
|
-
{attachments.map((attachment, index) => (
|
|
475
|
-
<FilePreview
|
|
476
|
-
key={index}
|
|
477
|
-
file={attachment.file}
|
|
478
|
-
type={attachment.type}
|
|
479
|
-
previewUrl={attachment.previewUrl}
|
|
480
|
-
onRemove={() => removeAttachment(index)}
|
|
481
|
-
/>
|
|
482
|
-
))}
|
|
483
|
-
|
|
484
|
-
{attachments.length < MAX_FILE_COUNT && (
|
|
485
|
-
<div className="add-more-files" onClick={() => fileInputRef.current?.click()}>
|
|
486
|
-
<div className="plus-icon">+</div>
|
|
487
|
-
<div className="add-more-text">Add more</div>
|
|
488
|
-
</div>
|
|
489
|
-
)}
|
|
490
|
-
</div>
|
|
491
|
-
|
|
492
|
-
<button
|
|
493
|
-
className="scroll-button right"
|
|
494
|
-
onClick={() => scrollAttachments('right')}
|
|
495
|
-
disabled={attachments.length <= 3}
|
|
496
|
-
>
|
|
497
|
-
>
|
|
498
|
-
</button>
|
|
499
|
-
</div>
|
|
500
|
-
)}
|
|
501
|
-
|
|
502
|
-
<form className="chatMessageInputform" onSubmit={handleSubmit}>
|
|
503
|
-
<div className="chatMessageInputdiv">
|
|
504
|
-
{/* Hidden file input */}
|
|
505
|
-
<input
|
|
506
|
-
type="file"
|
|
507
|
-
ref={fileInputRef}
|
|
508
|
-
style={{ display: 'none' }}
|
|
509
|
-
onChange={handleFileChange}
|
|
510
|
-
multiple
|
|
511
|
-
/>
|
|
512
|
-
|
|
513
|
-
{/* Attachment button and options */}
|
|
514
|
-
<div className="attachment-container" style={{ position: 'relative' }}>
|
|
463
|
+
{/* Preview area for attachments */}
|
|
464
|
+
{attachments.length > 0 && (
|
|
465
|
+
<div className="attachments-preview-container">
|
|
515
466
|
<button
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
style={{
|
|
520
|
-
background: 'none',
|
|
521
|
-
border: 'none',
|
|
522
|
-
cursor: 'pointer',
|
|
523
|
-
padding: '8px',
|
|
524
|
-
}}
|
|
467
|
+
className="scroll-button left"
|
|
468
|
+
onClick={() => scrollAttachments('left')}
|
|
469
|
+
disabled={attachments.length <= 3}
|
|
525
470
|
>
|
|
526
|
-
|
|
527
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
528
|
-
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
|
|
529
|
-
</svg>
|
|
530
|
-
</div>
|
|
471
|
+
<
|
|
531
472
|
</button>
|
|
532
473
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
<
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
<
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
</svg>
|
|
560
|
-
</div>
|
|
561
|
-
<span>Document</span>
|
|
562
|
-
</button>
|
|
563
|
-
</div>
|
|
564
|
-
)}
|
|
474
|
+
<div className="attachments-preview" ref={attachmentsContainerRef}>
|
|
475
|
+
{attachments.map((attachment, index) => (
|
|
476
|
+
<FilePreview
|
|
477
|
+
key={index}
|
|
478
|
+
file={attachment.file}
|
|
479
|
+
type={attachment.type}
|
|
480
|
+
previewUrl={attachment.previewUrl}
|
|
481
|
+
onRemove={() => removeAttachment(index)}
|
|
482
|
+
/>
|
|
483
|
+
))}
|
|
484
|
+
|
|
485
|
+
{attachments.length < MAX_FILE_COUNT && (
|
|
486
|
+
<div className="add-more-files" onClick={() => fileInputRef.current?.click()}>
|
|
487
|
+
<div className="plus-icon">+</div>
|
|
488
|
+
<div className="add-more-text">Add more</div>
|
|
489
|
+
</div>
|
|
490
|
+
)}
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
<button
|
|
494
|
+
className="scroll-button right"
|
|
495
|
+
onClick={() => scrollAttachments('right')}
|
|
496
|
+
disabled={attachments.length <= 3}
|
|
497
|
+
>
|
|
498
|
+
>
|
|
499
|
+
</button>
|
|
565
500
|
</div>
|
|
501
|
+
)}
|
|
566
502
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
503
|
+
<form className="chatMessageInputform" onSubmit={handleSubmit}>
|
|
504
|
+
{inputError && <p style={{ color: 'red', fontSize: '12px' }}>{inputError}</p>}
|
|
505
|
+
|
|
506
|
+
<div className="chatMessageInputdiv">
|
|
507
|
+
{/* Hidden file input */}
|
|
508
|
+
<input
|
|
509
|
+
type="file"
|
|
510
|
+
ref={fileInputRef}
|
|
511
|
+
style={{ display: 'none' }}
|
|
512
|
+
onChange={handleFileChange}
|
|
513
|
+
multiple
|
|
514
|
+
/>
|
|
515
|
+
|
|
516
|
+
{/* Attachment button and options */}
|
|
517
|
+
<div className="attachment-container" style={{ position: 'relative' }}>
|
|
518
|
+
<button
|
|
519
|
+
type="button"
|
|
520
|
+
className="attachment-button"
|
|
521
|
+
onClick={handleAttachmentClick}
|
|
522
|
+
style={{
|
|
523
|
+
background: 'none',
|
|
524
|
+
border: 'none',
|
|
525
|
+
cursor: 'pointer',
|
|
526
|
+
padding: '8px',
|
|
527
|
+
}}
|
|
528
|
+
>
|
|
529
|
+
<div className="attachment-icon">
|
|
530
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
531
|
+
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
|
|
532
|
+
</svg>
|
|
533
|
+
</div>
|
|
534
|
+
</button>
|
|
535
|
+
|
|
536
|
+
{showAttachmentOptions && (
|
|
537
|
+
<div className="attachment-options">
|
|
538
|
+
<button
|
|
539
|
+
type="button"
|
|
540
|
+
onClick={() => handleFileSelect('image')}
|
|
541
|
+
>
|
|
542
|
+
<div className="icon">
|
|
543
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
544
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
545
|
+
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
|
546
|
+
<polyline points="21 15 16 10 5 21"></polyline>
|
|
547
|
+
</svg>
|
|
548
|
+
</div>
|
|
549
|
+
<span>Photos & videos</span>
|
|
550
|
+
</button>
|
|
551
|
+
<button
|
|
552
|
+
type="button"
|
|
553
|
+
onClick={() => handleFileSelect('document')}
|
|
554
|
+
>
|
|
555
|
+
<div className="icon">
|
|
556
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
557
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
558
|
+
<polyline points="14 2 14 8 20 8"></polyline>
|
|
559
|
+
<line x1="16" y1="13" x2="8" y2="13"></line>
|
|
560
|
+
<line x1="16" y1="17" x2="8" y2="17"></line>
|
|
561
|
+
<polyline points="10 9 9 9 8 9"></polyline>
|
|
562
|
+
</svg>
|
|
563
|
+
</div>
|
|
564
|
+
<span>Document</span>
|
|
565
|
+
</button>
|
|
566
|
+
</div>
|
|
567
|
+
)}
|
|
599
568
|
</div>
|
|
569
|
+
|
|
570
|
+
<textarea
|
|
571
|
+
className="chatMessageInput"
|
|
572
|
+
placeholder="Send a message"
|
|
573
|
+
value={message}
|
|
574
|
+
// onChange={(e) => {
|
|
575
|
+
// setMessage(e.target.value)
|
|
576
|
+
// autoResizeTextarea(e.target)
|
|
577
|
+
// }}
|
|
578
|
+
onChange={handleChange}
|
|
579
|
+
rows={1}
|
|
580
|
+
style={{ resize: "none" }}
|
|
581
|
+
onKeyDown={(e) => {
|
|
582
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
583
|
+
e.preventDefault()
|
|
584
|
+
handleSubmit(e)
|
|
585
|
+
}
|
|
586
|
+
}}
|
|
587
|
+
/>
|
|
588
|
+
|
|
589
|
+
<button type="submit" className="chatMessageInputSubmit" disabled={!!inputError || isSending}>
|
|
590
|
+
<img width={10} height={10} src={paperplane} alt="send" />
|
|
591
|
+
</button>
|
|
600
592
|
</div>
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
593
|
+
|
|
594
|
+
{typingUser && typingUser !== userId && typingUser === selectedConversation?.participantDetails?._id && !isSending && (
|
|
595
|
+
<div className="typingIndicator">
|
|
596
|
+
<div className="typing-loader">
|
|
597
|
+
<div className="ball" />
|
|
598
|
+
<div className="ball" />
|
|
599
|
+
<div className="ball" />
|
|
600
|
+
typing
|
|
601
|
+
</div>
|
|
602
|
+
</div>
|
|
603
|
+
)}
|
|
604
|
+
</form>
|
|
605
|
+
</div>
|
|
604
606
|
);
|
|
605
607
|
};
|
|
606
608
|
|
|
@@ -12,7 +12,7 @@ const Conversations = () => {
|
|
|
12
12
|
// const { loading, conversations } = useGetConversations();
|
|
13
13
|
return (
|
|
14
14
|
<div className="chatSidebarConversations">
|
|
15
|
-
<h2 className="text-lg font-semibold text-gray-700">All Messages</h2>
|
|
15
|
+
<h2 className="text-lg font-semibold text-gray-700" style={{paddingLeft:'1rem'}}>All Messages</h2>
|
|
16
16
|
{(!conversations || conversations.length === 0) && (
|
|
17
17
|
<div className="flex flex-col items-center justify-center p-8 text-center">
|
|
18
18
|
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-gray-100 mb-4">
|
package/src/style/style.css
CHANGED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
padding-bottom: 3px;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
.loader-wrapper{
|
|
76
|
+
.loader-wrapper {
|
|
77
77
|
display: flex;
|
|
78
78
|
align-items: center;
|
|
79
79
|
justify-content: center;
|
|
@@ -82,22 +82,24 @@
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
.chatSidebarInput {
|
|
85
|
-
outline: none;
|
|
86
|
-
padding: 8px 4px;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
outline: none;
|
|
86
|
+
padding: 8px 4px;
|
|
87
|
+
/* Keep original padding */
|
|
88
|
+
font-size: 1rem;
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
line-height: 1.5rem;
|
|
91
|
+
font-weight: 400;
|
|
92
|
+
border: 1px solid #ccc;
|
|
93
|
+
width: 100%;
|
|
94
|
+
/* Ensure full width */
|
|
95
|
+
/* min-width: 400px; */
|
|
96
|
+
max-width: 600px;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
.chatSidebarInput:focus {
|
|
98
|
-
border: 1px solid #12bbb5 !important;
|
|
99
|
-
box-shadow: 0 0 5px rgba(18, 187, 181, 0.5);
|
|
100
|
-
transition: border-color 0.3s ease-in-out;
|
|
100
|
+
border: 1px solid #12bbb5 !important;
|
|
101
|
+
box-shadow: 0 0 5px rgba(18, 187, 181, 0.5);
|
|
102
|
+
transition: border-color 0.3s ease-in-out;
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
.chatSidebarConversations {
|
|
@@ -122,7 +124,7 @@ transition: border-color 0.3s ease-in-out;
|
|
|
122
124
|
/* height: 72px; */
|
|
123
125
|
|
|
124
126
|
:hover {
|
|
125
|
-
|
|
127
|
+
background-color: transparent;
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
|
|
@@ -210,8 +212,8 @@ transition: border-color 0.3s ease-in-out;
|
|
|
210
212
|
|
|
211
213
|
.chatMessageContainerOutter {
|
|
212
214
|
display: inline-flex;
|
|
213
|
-
flex-basis: 0px;
|
|
214
|
-
flex-direction: column;
|
|
215
|
+
/* flex-basis: 0px;
|
|
216
|
+
flex-direction: column; */
|
|
215
217
|
shrink: 1;
|
|
216
218
|
gap: 0.25rem;
|
|
217
219
|
justify-content: flex-start;
|
|
@@ -266,7 +268,7 @@ transition: border-color 0.3s ease-in-out;
|
|
|
266
268
|
.chatMessagesBubble_me {
|
|
267
269
|
float: right;
|
|
268
270
|
color: white;
|
|
269
|
-
background-color: #076663;
|
|
271
|
+
background-color: #076663;
|
|
270
272
|
padding: 0.5rem 0.875rem;
|
|
271
273
|
}
|
|
272
274
|
|
|
@@ -274,7 +276,7 @@ transition: border-color 0.3s ease-in-out;
|
|
|
274
276
|
float: left;
|
|
275
277
|
background-color: #f3f4f6;
|
|
276
278
|
color: #374151;
|
|
277
|
-
padding: 0.5rem 0.875rem;
|
|
279
|
+
padding: 0.5rem 0.875rem;
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
.chatMessage {
|
|
@@ -309,10 +311,10 @@ transition: border-color 0.3s ease-in-out;
|
|
|
309
311
|
|
|
310
312
|
.chatMessagesBubble_Time {
|
|
311
313
|
display: block;
|
|
312
|
-
text-align: right;
|
|
313
|
-
font-size: 10px;
|
|
314
|
-
color: #d1d1d1;
|
|
315
|
-
margin-top: 5px;
|
|
314
|
+
text-align: right;
|
|
315
|
+
font-size: 10px;
|
|
316
|
+
color: #d1d1d1;
|
|
317
|
+
margin-top: 5px;
|
|
316
318
|
}
|
|
317
319
|
|
|
318
320
|
.chatMessageInputform {
|
|
@@ -326,6 +328,7 @@ margin-top: 5px;
|
|
|
326
328
|
margin-top: 0.75rem;
|
|
327
329
|
/* margin-bottom: 0.75rem; */
|
|
328
330
|
}
|
|
331
|
+
|
|
329
332
|
.chatMessageInputdiv {
|
|
330
333
|
display: flex;
|
|
331
334
|
align-items: center;
|
|
@@ -350,7 +353,8 @@ margin-top: 5px;
|
|
|
350
353
|
line-height: 1.25rem;
|
|
351
354
|
overflow-y: auto; */
|
|
352
355
|
outline: none;
|
|
353
|
-
padding: 8px 4px;
|
|
356
|
+
padding: 8px 4px;
|
|
357
|
+
/* Keep original padding */
|
|
354
358
|
font-size: 1rem;
|
|
355
359
|
border-radius: 4px;
|
|
356
360
|
line-height: 1.5rem;
|
|
@@ -361,17 +365,18 @@ margin-top: 5px;
|
|
|
361
365
|
min-height: 1.47em;
|
|
362
366
|
white-space: pre-wrap;
|
|
363
367
|
word-break: break-all;
|
|
364
|
-
overflow-y: auto;
|
|
368
|
+
overflow-y: auto;
|
|
369
|
+
/* Allow vertical scrolling if needed */
|
|
365
370
|
}
|
|
366
371
|
|
|
367
372
|
.chatMessageInput:focus {
|
|
368
|
-
border: 1px solid #12bbb5 !important;
|
|
369
|
-
box-shadow: 0 0 5px rgba(18, 187, 181, 0.5);
|
|
370
|
-
transition: border-color 0.3s ease-in-out;
|
|
373
|
+
border: 1px solid #12bbb5 !important;
|
|
374
|
+
box-shadow: 0 0 5px rgba(18, 187, 181, 0.5);
|
|
375
|
+
transition: border-color 0.3s ease-in-out;
|
|
371
376
|
}
|
|
372
377
|
|
|
373
378
|
.chatMessageInput::-webkit-scrollbar {
|
|
374
|
-
display: none;
|
|
379
|
+
display: none;
|
|
375
380
|
}
|
|
376
381
|
|
|
377
382
|
.chatMessageInputSubmit {
|
|
@@ -386,54 +391,54 @@ display: none;
|
|
|
386
391
|
}
|
|
387
392
|
|
|
388
393
|
.chat-container {
|
|
389
|
-
width: 100%;
|
|
390
|
-
font-family: Arial, sans-serif;
|
|
394
|
+
width: 100%;
|
|
395
|
+
font-family: Arial, sans-serif;
|
|
391
396
|
}
|
|
392
397
|
|
|
393
398
|
.message-row {
|
|
394
|
-
display: flex;
|
|
395
|
-
align-items: flex-end;
|
|
396
|
-
margin-bottom: 16px;
|
|
397
|
-
gap: 10px;
|
|
398
|
-
word-break: break-all;
|
|
399
|
-
max-width: 100%;
|
|
399
|
+
display: flex;
|
|
400
|
+
align-items: flex-end;
|
|
401
|
+
margin-bottom: 16px;
|
|
402
|
+
gap: 10px;
|
|
403
|
+
word-break: break-all;
|
|
404
|
+
max-width: 100%;
|
|
400
405
|
|
|
401
406
|
}
|
|
402
407
|
|
|
403
408
|
.message-row.incoming {
|
|
404
|
-
justify-content: flex-start;
|
|
409
|
+
justify-content: flex-start;
|
|
405
410
|
}
|
|
406
411
|
|
|
407
412
|
.message-row.outgoing {
|
|
408
|
-
justify-content: flex-end;
|
|
413
|
+
justify-content: flex-end;
|
|
409
414
|
}
|
|
410
415
|
|
|
411
416
|
|
|
412
417
|
.bubble-container {
|
|
413
|
-
display: flex;
|
|
414
|
-
flex-direction: column;
|
|
415
|
-
max-width: 70%;
|
|
418
|
+
display: flex;
|
|
419
|
+
flex-direction: column;
|
|
420
|
+
max-width: 70%;
|
|
416
421
|
}
|
|
417
422
|
|
|
418
423
|
.chat-bubble {
|
|
419
424
|
|
|
420
|
-
background-color: #f3f4f6;
|
|
421
|
-
border-radius: 0.5rem;
|
|
422
|
-
padding: 0.5rem;
|
|
423
|
-
font-size: 14px;
|
|
424
|
-
max-width: 20rem;
|
|
425
|
-
margin-bottom: 5px;
|
|
425
|
+
background-color: #f3f4f6;
|
|
426
|
+
border-radius: 0.5rem;
|
|
427
|
+
padding: 0.5rem;
|
|
428
|
+
font-size: 14px;
|
|
429
|
+
max-width: 20rem;
|
|
430
|
+
margin-bottom: 5px;
|
|
426
431
|
}
|
|
427
432
|
|
|
428
433
|
.outgoing .chat-bubble {
|
|
429
|
-
background-color: #12bbb5;
|
|
430
|
-
color: white;
|
|
434
|
+
background-color: #12bbb5;
|
|
435
|
+
color: white;
|
|
431
436
|
|
|
432
437
|
}
|
|
433
438
|
|
|
434
439
|
.incoming .chat-bubble {
|
|
435
|
-
background-color: #dedee4b9;
|
|
436
|
-
color: black;
|
|
440
|
+
background-color: #dedee4b9;
|
|
441
|
+
color: black;
|
|
437
442
|
}
|
|
438
443
|
|
|
439
444
|
.timestamp_incomeing {
|
|
@@ -446,35 +451,35 @@ color: black;
|
|
|
446
451
|
float: left;
|
|
447
452
|
position: relative;
|
|
448
453
|
justify-content: start;
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
.timestamp_outgoing {
|
|
458
|
+
font-size: 11px;
|
|
459
|
+
color: #888;
|
|
460
|
+
margin-top: 4px;
|
|
461
|
+
text-align: right;
|
|
462
|
+
display: flex;
|
|
463
|
+
align-items: center;
|
|
464
|
+
float: right;
|
|
465
|
+
position: relative;
|
|
466
|
+
justify-content: end;
|
|
467
|
+
}
|
|
463
468
|
|
|
464
469
|
.status-icon {
|
|
465
470
|
|
|
466
|
-
bottom: 5px;
|
|
467
|
-
margin-left: 10px;
|
|
468
|
-
right: 10px;
|
|
469
|
-
font-size: 12px;
|
|
471
|
+
bottom: 5px;
|
|
472
|
+
margin-left: 10px;
|
|
473
|
+
right: 10px;
|
|
474
|
+
font-size: 12px;
|
|
470
475
|
}
|
|
471
476
|
|
|
472
477
|
.read {
|
|
473
|
-
color: blue;
|
|
478
|
+
color: blue;
|
|
474
479
|
}
|
|
475
480
|
|
|
476
|
-
.text-sm{
|
|
477
|
-
font-size: .875rem;
|
|
481
|
+
.text-sm {
|
|
482
|
+
font-size: .875rem;
|
|
478
483
|
}
|
|
479
484
|
|
|
480
485
|
/* @media (min-width: 640px) {
|
|
@@ -500,47 +505,47 @@ font-size: .875rem;
|
|
|
500
505
|
|
|
501
506
|
@media (min-width: 768px) {
|
|
502
507
|
.grid-container {
|
|
503
|
-
|
|
504
|
-
|
|
508
|
+
height: 550px;
|
|
509
|
+
grid-template-columns: repeat(9, minmax(0, 1fr));
|
|
505
510
|
}
|
|
506
511
|
|
|
507
512
|
.sidebarContainer {
|
|
508
|
-
|
|
509
|
-
|
|
513
|
+
/* display: grid; */
|
|
514
|
+
grid-column: span 4;
|
|
510
515
|
}
|
|
511
516
|
|
|
512
517
|
.messageContainer {
|
|
513
|
-
|
|
514
|
-
|
|
518
|
+
display: grid;
|
|
519
|
+
grid-column: span 5;
|
|
515
520
|
}
|
|
516
521
|
|
|
517
522
|
.chatMessageContainerInnerDiv_button {
|
|
518
|
-
|
|
523
|
+
display: none;
|
|
519
524
|
}
|
|
520
525
|
|
|
521
526
|
.chatMessages {
|
|
522
|
-
|
|
523
|
-
|
|
527
|
+
padding-left: 2rem;
|
|
528
|
+
padding-right: 2rem;
|
|
524
529
|
}
|
|
525
530
|
|
|
526
531
|
}
|
|
527
532
|
|
|
528
|
-
.typingIndicator{
|
|
533
|
+
.typingIndicator {
|
|
529
534
|
display: flex;
|
|
530
535
|
align-items: center;
|
|
531
|
-
gap: 0.
|
|
536
|
+
gap: 0.2rem;
|
|
532
537
|
}
|
|
533
538
|
|
|
534
|
-
/* From Uiverse.io by ashish-yadv */
|
|
539
|
+
/* From Uiverse.io by ashish-yadv */
|
|
535
540
|
.typing-loader {
|
|
536
541
|
width: 60px;
|
|
537
542
|
display: flex;
|
|
538
543
|
align-items: center;
|
|
539
|
-
height: 100%;
|
|
540
|
-
margin-right: 10px;
|
|
541
|
-
width: 100%;
|
|
544
|
+
height: 100%;
|
|
545
|
+
margin-right: 10px;
|
|
546
|
+
width: 100%;
|
|
542
547
|
font-size: smaller;
|
|
543
|
-
gap: 0.
|
|
548
|
+
gap: 0.3rem;
|
|
544
549
|
}
|
|
545
550
|
|
|
546
551
|
.ball {
|
|
@@ -580,7 +585,7 @@ width: 100%;
|
|
|
580
585
|
}
|
|
581
586
|
}
|
|
582
587
|
|
|
583
|
-
/* From Uiverse.io by abrahamcalsin */
|
|
588
|
+
/* From Uiverse.io by abrahamcalsin */
|
|
584
589
|
.dot-spinner {
|
|
585
590
|
--uib-size: 2.8rem;
|
|
586
591
|
--uib-speed: .9s;
|
|
@@ -674,166 +679,168 @@ width: 100%;
|
|
|
674
679
|
|
|
675
680
|
/* Sidebar Container */
|
|
676
681
|
.chatSidebar {
|
|
677
|
-
background: #ffffff;
|
|
678
|
-
padding: 15px;
|
|
679
|
-
border-radius: 10px;
|
|
680
|
-
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
|
681
|
-
width: 300px;
|
|
682
|
+
background: #ffffff;
|
|
683
|
+
padding: 15px;
|
|
684
|
+
border-radius: 10px;
|
|
685
|
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
|
686
|
+
width: 300px;
|
|
682
687
|
}
|
|
683
688
|
|
|
684
689
|
/* Chat List */
|
|
685
690
|
.chatItem {
|
|
686
|
-
display: flex;
|
|
687
|
-
align-items: center;
|
|
688
|
-
padding: 12px;
|
|
689
|
-
border-radius: 8px;
|
|
690
|
-
transition: background 0.3s;
|
|
691
|
+
display: flex;
|
|
692
|
+
align-items: center;
|
|
693
|
+
padding: 12px;
|
|
694
|
+
border-radius: 8px;
|
|
695
|
+
transition: background 0.3s;
|
|
691
696
|
}
|
|
692
697
|
|
|
693
698
|
.chatItem:hover {
|
|
694
|
-
background: #f0f0f0;
|
|
695
|
-
cursor: pointer;
|
|
699
|
+
background: #f0f0f0;
|
|
700
|
+
cursor: pointer;
|
|
696
701
|
}
|
|
697
702
|
|
|
698
703
|
/* Profile Images */
|
|
699
704
|
.chatAvatar {
|
|
700
|
-
width: 40px;
|
|
701
|
-
height: 40px;
|
|
702
|
-
border-radius: 50%;
|
|
703
|
-
margin-right: 12px;
|
|
704
|
-
border: 2px solid #ccc;
|
|
705
|
-
transition: transform 0.3s ease-in-out;
|
|
705
|
+
width: 40px;
|
|
706
|
+
height: 40px;
|
|
707
|
+
border-radius: 50%;
|
|
708
|
+
margin-right: 12px;
|
|
709
|
+
border: 2px solid #ccc;
|
|
710
|
+
transition: transform 0.3s ease-in-out;
|
|
706
711
|
}
|
|
707
712
|
|
|
708
713
|
.chatAvatar:hover {
|
|
709
|
-
transform: scale(1.1);
|
|
714
|
+
transform: scale(1.1);
|
|
710
715
|
}
|
|
711
716
|
|
|
712
717
|
/* Chat Details */
|
|
713
718
|
.chatDetails {
|
|
714
|
-
flex-grow: 1;
|
|
719
|
+
flex-grow: 1;
|
|
715
720
|
}
|
|
716
721
|
|
|
717
722
|
.chatName {
|
|
718
|
-
font-weight: 600;
|
|
719
|
-
color: #333;
|
|
723
|
+
font-weight: 600;
|
|
724
|
+
color: #333;
|
|
720
725
|
}
|
|
721
726
|
|
|
722
727
|
.chatMessage {
|
|
723
|
-
font-size: 0.9rem;
|
|
724
|
-
color: #777;
|
|
728
|
+
font-size: 0.9rem;
|
|
729
|
+
color: #777;
|
|
725
730
|
}
|
|
726
731
|
|
|
727
732
|
/* Chat Time */
|
|
728
733
|
.chatTime {
|
|
729
|
-
font-size: 0.8rem;
|
|
730
|
-
color: #aaa;
|
|
734
|
+
font-size: 0.8rem;
|
|
735
|
+
color: #aaa;
|
|
731
736
|
}
|
|
732
737
|
|
|
733
738
|
|
|
734
739
|
|
|
735
740
|
/* Position the status dot on the corner of the profile picture */
|
|
736
741
|
.chatSidebarConversationImg {
|
|
737
|
-
position: relative;
|
|
738
|
-
width: 3rem;
|
|
739
|
-
height: 3rem;
|
|
740
|
-
border-radius: 100%;
|
|
742
|
+
position: relative;
|
|
743
|
+
width: 3rem;
|
|
744
|
+
height: 3rem;
|
|
745
|
+
border-radius: 100%;
|
|
741
746
|
}
|
|
742
747
|
|
|
743
748
|
/* The status dot */
|
|
744
749
|
.chatSidebarStatusDot {
|
|
745
|
-
position: absolute;
|
|
746
|
-
bottom: 0;
|
|
747
|
-
right: 0;
|
|
748
|
-
width: 12px;
|
|
749
|
-
height: 12px;
|
|
750
|
-
border-radius: 50%;
|
|
751
|
-
border: 2px solid white;
|
|
750
|
+
position: absolute;
|
|
751
|
+
bottom: 0;
|
|
752
|
+
right: 0;
|
|
753
|
+
width: 12px;
|
|
754
|
+
height: 12px;
|
|
755
|
+
border-radius: 50%;
|
|
756
|
+
border: 2px solid white;
|
|
757
|
+
/* Border for a neat appearance */
|
|
752
758
|
}
|
|
753
759
|
|
|
754
760
|
|
|
755
761
|
/* For online status */
|
|
756
762
|
.chatSidebarStatusDot.online {
|
|
757
|
-
background-color: green;
|
|
763
|
+
background-color: green;
|
|
758
764
|
}
|
|
759
765
|
|
|
760
766
|
/* For offline status */
|
|
761
767
|
.chatSidebarStatusDot.offline {
|
|
762
|
-
background-color: rgba(179, 170, 170, 0.712);
|
|
768
|
+
background-color: rgba(179, 170, 170, 0.712);
|
|
763
769
|
}
|
|
764
770
|
|
|
765
771
|
.conversation-container {
|
|
766
|
-
display: flex;
|
|
767
|
-
align-items: center;
|
|
768
|
-
gap: 12px;
|
|
769
|
-
padding: 12px;
|
|
770
|
-
/* border-radius: 8px; */
|
|
771
|
-
border-bottom: .5px solid lightgray;
|
|
772
|
-
background-color: white;
|
|
773
|
-
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); */
|
|
774
|
-
cursor: pointer;
|
|
775
|
-
transition: background-color 0.3s ease-in-out;
|
|
772
|
+
display: flex;
|
|
773
|
+
align-items: center;
|
|
774
|
+
gap: 12px;
|
|
775
|
+
padding: 12px;
|
|
776
|
+
/* border-radius: 8px; */
|
|
777
|
+
border-bottom: .5px solid lightgray;
|
|
778
|
+
background-color: white;
|
|
779
|
+
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); */
|
|
780
|
+
cursor: pointer;
|
|
781
|
+
transition: background-color 0.3s ease-in-out;
|
|
776
782
|
}
|
|
777
783
|
|
|
778
784
|
.conversation-container:hover {
|
|
779
|
-
background-color: #f5f5f5;
|
|
785
|
+
background-color: #f5f5f5;
|
|
780
786
|
}
|
|
781
787
|
|
|
782
788
|
.conversation-avatar {
|
|
783
|
-
position: relative;
|
|
789
|
+
position: relative;
|
|
784
790
|
}
|
|
785
791
|
|
|
786
792
|
.conversation-img {
|
|
787
|
-
width: 48px;
|
|
788
|
-
height: 48px;
|
|
789
|
-
border-radius: 50%;
|
|
790
|
-
border: 2px solid #ccc;
|
|
791
|
-
transition: border-color 0.3s;
|
|
793
|
+
width: 48px;
|
|
794
|
+
height: 48px;
|
|
795
|
+
border-radius: 50%;
|
|
796
|
+
border: 2px solid #ccc;
|
|
797
|
+
transition: border-color 0.3s;
|
|
792
798
|
}
|
|
793
799
|
|
|
794
800
|
.conversation-img:hover {
|
|
795
|
-
border-color: #12bbb5;
|
|
801
|
+
border-color: #12bbb5;
|
|
796
802
|
}
|
|
797
803
|
|
|
798
804
|
|
|
799
805
|
.conversation-info {
|
|
800
|
-
flex-grow: 1;
|
|
801
|
-
display: flex;
|
|
802
|
-
flex-direction: column;
|
|
806
|
+
flex-grow: 1;
|
|
807
|
+
display: flex;
|
|
808
|
+
flex-direction: column;
|
|
803
809
|
}
|
|
804
810
|
|
|
805
811
|
.conversation-header {
|
|
806
|
-
display: flex;
|
|
807
|
-
justify-content: space-between;
|
|
808
|
-
align-items: center;
|
|
812
|
+
display: flex;
|
|
813
|
+
justify-content: space-between;
|
|
814
|
+
align-items: center;
|
|
809
815
|
}
|
|
810
816
|
|
|
811
817
|
.conversation-name {
|
|
812
|
-
font-size: 14px;
|
|
813
|
-
font-weight: bold;
|
|
814
|
-
color: #333;
|
|
818
|
+
font-size: 14px;
|
|
819
|
+
font-weight: bold;
|
|
820
|
+
color: #333;
|
|
815
821
|
}
|
|
816
822
|
|
|
817
823
|
.conversation-time {
|
|
818
|
-
font-size: 12px;
|
|
819
|
-
color: #777;
|
|
824
|
+
font-size: 12px;
|
|
825
|
+
color: #777;
|
|
820
826
|
}
|
|
821
827
|
|
|
822
828
|
.conversation-message {
|
|
823
|
-
font-size: 12px;
|
|
824
|
-
color: #777;
|
|
825
|
-
white-space: nowrap;
|
|
826
|
-
overflow: hidden;
|
|
827
|
-
text-overflow: ellipsis;
|
|
829
|
+
font-size: 12px;
|
|
830
|
+
color: #777;
|
|
831
|
+
white-space: nowrap;
|
|
832
|
+
overflow: hidden;
|
|
833
|
+
text-overflow: ellipsis;
|
|
828
834
|
}
|
|
829
835
|
|
|
830
836
|
.divider {
|
|
831
|
-
background-color: #ccc;
|
|
837
|
+
background-color: #ccc;
|
|
832
838
|
|
|
833
839
|
}
|
|
834
840
|
|
|
835
841
|
|
|
836
842
|
@keyframes pulse0112 {
|
|
843
|
+
|
|
837
844
|
0%,
|
|
838
845
|
100% {
|
|
839
846
|
transform: scale(0);
|
|
@@ -874,7 +881,8 @@ background-color: #ccc;
|
|
|
874
881
|
}
|
|
875
882
|
|
|
876
883
|
.attachments-preview::-webkit-scrollbar {
|
|
877
|
-
display: none;
|
|
884
|
+
display: none;
|
|
885
|
+
/* Hide scrollbar for Chrome/Safari */
|
|
878
886
|
}
|
|
879
887
|
|
|
880
888
|
.file-preview-wrapper {
|
|
@@ -897,7 +905,8 @@ background-color: #ccc;
|
|
|
897
905
|
.file-preview {
|
|
898
906
|
position: relative;
|
|
899
907
|
/* width: 246px; */
|
|
900
|
-
height: 100px;
|
|
908
|
+
height: 100px;
|
|
909
|
+
/* Increased height to accommodate filename */
|
|
901
910
|
border-radius: 8px;
|
|
902
911
|
overflow: hidden;
|
|
903
912
|
background: linear-gradient(135deg, #f9f9f9, #e9ecef);
|
|
@@ -940,7 +949,7 @@ background-color: #ccc;
|
|
|
940
949
|
|
|
941
950
|
.add-more-files:hover {
|
|
942
951
|
border-color: #999;
|
|
943
|
-
background: rgba(0,0,0,0.02);
|
|
952
|
+
background: rgba(0, 0, 0, 0.02);
|
|
944
953
|
}
|
|
945
954
|
|
|
946
955
|
.plus-icon {
|
|
@@ -979,6 +988,7 @@ background-color: #ccc;
|
|
|
979
988
|
object-fit: cover;
|
|
980
989
|
border-radius: 8px;
|
|
981
990
|
}
|
|
991
|
+
|
|
982
992
|
.file-preview-document span,
|
|
983
993
|
.file-name {
|
|
984
994
|
display: block;
|
|
@@ -1109,7 +1119,7 @@ background-color: #ccc;
|
|
|
1109
1119
|
left: 0;
|
|
1110
1120
|
background-color: white;
|
|
1111
1121
|
border-radius: 8px;
|
|
1112
|
-
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
|
1122
|
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
1113
1123
|
padding: 8px;
|
|
1114
1124
|
z-index: 1000;
|
|
1115
1125
|
display: flex;
|
|
@@ -1142,7 +1152,8 @@ background-color: #ccc;
|
|
|
1142
1152
|
|
|
1143
1153
|
.media-item {
|
|
1144
1154
|
background: #f3f4f6;
|
|
1145
|
-
border-radius: 0.375rem;
|
|
1155
|
+
border-radius: 0.375rem;
|
|
1156
|
+
/* reduced from 0.75rem */
|
|
1146
1157
|
padding: 0.5rem;
|
|
1147
1158
|
overflow: hidden;
|
|
1148
1159
|
display: flex;
|
|
@@ -1151,7 +1162,7 @@ background-color: #ccc;
|
|
|
1151
1162
|
width: 246px;
|
|
1152
1163
|
}
|
|
1153
1164
|
|
|
1154
|
-
.media-content{
|
|
1165
|
+
.media-content {
|
|
1155
1166
|
width: 100%;
|
|
1156
1167
|
object-fit: cover;
|
|
1157
1168
|
}
|
|
@@ -1159,7 +1170,8 @@ background-color: #ccc;
|
|
|
1159
1170
|
.media-preview {
|
|
1160
1171
|
max-width: 100%;
|
|
1161
1172
|
max-height: 200px;
|
|
1162
|
-
border-radius: 0.375rem;
|
|
1173
|
+
border-radius: 0.375rem;
|
|
1174
|
+
/* reduced from 0.5rem */
|
|
1163
1175
|
object-fit: cover;
|
|
1164
1176
|
}
|
|
1165
1177
|
|
|
@@ -1202,7 +1214,8 @@ background-color: #ccc;
|
|
|
1202
1214
|
.document-preview {
|
|
1203
1215
|
position: relative;
|
|
1204
1216
|
width: 246px;
|
|
1205
|
-
height: 60px;
|
|
1217
|
+
height: 60px;
|
|
1218
|
+
/* Increased height to accommodate filename */
|
|
1206
1219
|
border-radius: 12px;
|
|
1207
1220
|
overflow: hidden;
|
|
1208
1221
|
background: linear-gradient(135deg, #f9f9f9, #e9ecef);
|
|
@@ -1231,8 +1244,13 @@ background-color: #ccc;
|
|
|
1231
1244
|
}
|
|
1232
1245
|
|
|
1233
1246
|
@keyframes spin {
|
|
1234
|
-
0% {
|
|
1235
|
-
|
|
1247
|
+
0% {
|
|
1248
|
+
transform: rotate(0deg);
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
100% {
|
|
1252
|
+
transform: rotate(360deg);
|
|
1253
|
+
}
|
|
1236
1254
|
}
|
|
1237
1255
|
|
|
1238
1256
|
|