Add connecting state

This commit is contained in:
Bryan1029384756
2026-02-16 19:06:17 -06:00
parent ee376b9ba3
commit fca2ed8da9
5 changed files with 84 additions and 22 deletions

View File

@@ -150,7 +150,7 @@ const getProviderClass = (url) => {
return '';
};
const LinkPreview = ({ url }) => {
export const LinkPreview = ({ url }) => {
const { links } = usePlatform();
const [metadata, setMetadata] = useState(metadataCache.get(url) || null);
const [loading, setLoading] = useState(!metadataCache.has(url));
@@ -219,7 +219,7 @@ const LinkPreview = ({ url }) => {
if (metadata.description === 'Image File' && metadata.image) {
return (
<div className="preview-image-standalone" style={{ marginTop: 8, display: 'inline-block', maxWidth: '100%', cursor: 'pointer' }}>
<img src={metadata.image} alt="Preview" style={{ maxWidth: '100%', maxHeight: '350px', borderRadius: '8px', display: 'block' }} />
<img src={metadata.image} alt="Preview" draggable="false" style={{ maxWidth: '100%', maxHeight: '350px', borderRadius: '8px', display: 'block' }} />
</div>
);
}
@@ -251,18 +251,18 @@ const LinkPreview = ({ url }) => {
)}
{isLargeImage && !isYouTube && metadata.image && (
<div className="preview-image-container large-image">
<img src={metadata.image} alt="Preview" className="preview-image" />
<img src={metadata.image} alt="Preview" draggable="false" className="preview-image" />
</div>
)}
</div>
{!isLargeImage && !isYouTube && metadata.image && (
<div className="preview-image-container">
<img src={metadata.image} alt="Preview" className="preview-image" />
<img src={metadata.image} alt="Preview" draggable="false" className="preview-image" />
</div>
)}
{isYouTube && metadata.image && !playing && (
<div className="preview-image-container" onClick={() => setPlaying(true)} style={{ cursor: 'pointer' }}>
<img src={metadata.image} alt="Preview" className="preview-image" />
<img src={metadata.image} alt="Preview" draggable="false" className="preview-image" />
<div className="play-icon"></div>
</div>
)}
@@ -322,7 +322,7 @@ const Attachment = ({ metadata, onLoad, onImageClick }) => {
if (error) return <div style={{ color: '#ed4245', fontSize: '12px' }}>{error}</div>;
if (metadata.mimeType.startsWith('image/')) {
return <img src={url} alt={metadata.filename} style={{ maxHeight: '300px', borderRadius: '4px', cursor: 'zoom-in' }} onLoad={onLoad} onClick={() => onImageClick(url)} />;
return <img src={url} alt={metadata.filename} draggable="false" style={{ maxHeight: '300px', borderRadius: '4px', cursor: 'zoom-in' }} onLoad={onLoad} onClick={() => onImageClick(url)} />;
}
if (metadata.mimeType.startsWith('video/')) {
const handlePlayClick = () => { setShowControls(true); if (videoRef.current) videoRef.current.play(); };
@@ -1074,9 +1074,13 @@ const ChatArea = ({ channelId, channelName, channelType, username, channelKey, u
const processFile = (file) => { setPendingFiles(prev => [...prev, file]); };
const handleFileSelect = (e) => { if (e.target.files && e.target.files.length > 0) Array.from(e.target.files).forEach(processFile); };
const handleDragOver = (e) => { e.preventDefault(); e.stopPropagation(); if (!isDragging) setIsDragging(true); };
const isExternalFileDrag = (e) => {
const types = Array.from(e.dataTransfer.types);
return types.includes('Files') && !types.includes('text/uri-list') && !types.includes('text/html');
};
const handleDragOver = (e) => { if (!isExternalFileDrag(e)) return; e.preventDefault(); e.stopPropagation(); if (!isDragging) setIsDragging(true); };
const handleDragLeave = (e) => { e.preventDefault(); e.stopPropagation(); if (e.currentTarget.contains(e.relatedTarget)) return; setIsDragging(false); };
const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) Array.from(e.dataTransfer.files).forEach(processFile); };
const handleDrop = (e) => { if (!isDragging) return; e.preventDefault(); e.stopPropagation(); setIsDragging(false); if (e.dataTransfer.files && e.dataTransfer.files.length > 0) Array.from(e.dataTransfer.files).forEach(processFile); };
const uploadAndSendFile = async (file) => {
const fileKey = await crypto.randomBytes(32);
@@ -1477,6 +1481,7 @@ const ChatArea = ({ channelId, channelName, channelType, username, channelKey, u
{uploading ? <div className="spinner" style={{ width: 24, height: 24, borderRadius: '50%', border: '2px solid #b9bbbe', borderTopColor: 'transparent', animation: 'spin 1s linear infinite' }}></div> : <ColoredIcon src={AddIcon} color={ICON_COLOR_DEFAULT} size="24px" />}
</button>
<div ref={inputDivRef} contentEditable className="chat-input-richtext" role="textbox" aria-multiline="true"
onDrop={(e) => e.preventDefault()}
onBlur={saveSelection}
onMouseUp={saveSelection}
onKeyUp={saveSelection}