- {messages.map((msg, idx) => (
-
-
-
{msg.username || 'Unknown'}
-
{new Date(msg.created_at).toLocaleTimeString()}
+ {messages.map((msg, idx) => {
+ const urls = extractUrls(msg.content);
+ return (
+
+
+
+ {(msg.username || '?').substring(0, 1).toUpperCase()}
+
+
+
+
+
+ {msg.username || 'Unknown'}
+
+
+ {new Date(msg.created_at).toLocaleDateString()} at {new Date(msg.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
+
+
+
+
(
+ {
+ e.preventDefault();
+ window.cryptoAPI.openExternal(props.href);
+ }}
+ style={{ color: '#00b0f4', cursor: 'pointer', textDecoration: 'none' }}
+ onMouseOver={(e) => e.target.style.textDecoration = 'underline'}
+ onMouseOut={(e) => e.target.style.textDecoration = 'none'}
+ />
+ ),
+ code({ node, inline, className, children, ...props }) {
+ const match = /language-(\w+)/.exec(className || '')
+ return !inline && match ? (
+
+ {String(children).replace(/\n$/, '')}
+
+ ) : (
+
+ {children}
+
+ )
+ },
+ p: ({ node, ...props }) => ,
+ h1: ({ node, ...props }) => ,
+ h2: ({ node, ...props }) => ,
+ h3: ({ node, ...props }) => ,
+ ul: ({ node, ...props }) => ,
+ ol: ({ node, ...props }) =>
,
+ li: ({ node, ...props }) => ,
+ hr: ({ node, ...props }) =>
,
+ }}
+ >
+ {msg.content}
+
+ {urls.map((url, i) => (
+
+ ))}
+
+
-
-
- {String(children).replace(/\n$/, '')}
-
- ) : (
-
- {children}
-
- )
- }
- }}
- >
- {msg.content}
-
-
-
- ))}
+ );
+ })}
);
diff --git a/Frontend/Electron/src/index.css b/Frontend/Electron/src/index.css
index bd2c450..9379193 100644
--- a/Frontend/Electron/src/index.css
+++ b/Frontend/Electron/src/index.css
@@ -31,7 +31,6 @@ body {
justify-content: center;
height: 100vh;
background-image: url('https://discord.com/assets/f9e794909795f472.svg');
- /* Placeholder background */
background-size: cover;
background-position: center;
}
@@ -122,6 +121,7 @@ body {
/* Sidebar */
.sidebar {
width: 300px;
+ min-width: 300px;
background-color: var(--bg-secondary);
display: flex;
flex-direction: row;
@@ -201,28 +201,71 @@ body {
background-color: var(--bg-primary);
display: flex;
flex-direction: column;
+ position: relative;
}
.messages-list {
flex: 1;
overflow-y: auto;
- padding: 20px;
+ padding: 0 0 20px 0;
+ display: flex;
+ flex-direction: column;
+}
+
+.messages-list::-webkit-scrollbar {
+ width: 8px;
+ background-color: #2b2d31;
+}
+
+.messages-list::-webkit-scrollbar-thumb {
+ background-color: #1a1b1e;
+ border-radius: 4px;
}
.message-item {
- margin-bottom: 20px;
+ display: flex;
+ padding: 2px 16px;
+ margin-top: 17px;
+}
+
+.message-item:hover {
+ background-color: rgba(2, 2, 2, 0.06);
+}
+
+.message-avatar-wrapper {
+ width: 40px;
+ margin-right: 16px;
+ margin-top: 2px;
+}
+
+.message-avatar {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: 500;
+ color: white;
+ font-size: 18px;
+ user-select: none;
+}
+
+.message-body {
+ flex: 1;
+ min-width: 0;
}
.message-header {
display: flex;
- align-items: baseline;
- margin-bottom: 4px;
+ align-items: center;
+ margin-bottom: 2px;
}
.username {
- color: var(--header-primary);
+ font-size: 16px;
font-weight: 500;
- margin-right: 8px;
+ margin-right: 0.25rem;
cursor: pointer;
}
@@ -232,54 +275,267 @@ body {
.timestamp {
color: var(--text-muted);
- font-size: 12px;
+ font-size: 0.75rem;
+ margin-left: 0.25rem;
+ font-weight: 400;
}
.message-content {
color: var(--text-normal);
+ font-size: 1rem;
+ line-height: 1.375rem;
white-space: pre-wrap;
word-wrap: break-word;
}
-.chat-input-form {
- padding: 0 16px 24px;
+/* Markdown Styles Tweaks */
+.message-content strong {
+ font-weight: 700;
}
-.chat-input-form textarea {
- width: 100%;
- padding: 11px 16px;
- background-color: #40444b;
- border: none;
- border-radius: 8px;
- color: var(--text-normal);
- font-size: 16px;
- font-family: inherit;
- height: auto;
- min-height: 44px;
+.message-content h1,
+.message-content h2,
+.message-content h3 {
+ border-bottom: none;
+ font-weight: 700;
+ color: var(--header-primary);
}
-.chat-input-form textarea:focus {
- outline: none;
+.message-content ul,
+.message-content ol {
+ list-style-type: disc;
}
-/* Markdown Styles */
-.message-content p {
- margin: 0;
+.message-content a {
+ color: #00b0f4;
+ text-decoration: none;
+}
+
+.message-content a:hover {
+ text-decoration: underline;
+}
+
+.message-content blockquote {
+ border-left: 4px solid #4f545c;
+ margin: 4px 0 4px 0;
+ padding: 0 8px 0 12px;
+ color: #b9bbbe;
+ background-color: transparent;
}
.message-content code {
background-color: #2f3136;
padding: 2px 4px;
border-radius: 3px;
- font-family: monospace;
+ font-family: Consolas, 'Courier New', monospace;
+ font-size: 0.875rem;
}
.message-content pre {
- margin: 6px 0;
+ background-color: #2f3136 !important;
+ border-radius: 4px;
+ border: 1px solid #202225;
+ padding: 8px !important;
+ margin: 8px 0 !important;
+ max-width: 100%;
+ overflow-x: auto;
}
-.message-content blockquote {
- border-left: 4px solid var(--interactive-normal);
- margin: 0;
- padding-left: 10px;
+.chat-input-form {
+ padding: 0 16px 24px;
+ margin-top: 8px;
+ background-color: var(--bg-primary);
+}
+
+.chat-input-wrapper {
+ background-color: #40444b;
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ padding: 0 16px;
+ min-height: 44px;
+}
+
+.chat-input-file-btn {
+ background: none;
+ border: none;
+ color: #b9bbbe;
+ cursor: pointer;
+ padding: 0 16px 0 0;
+ display: flex;
+ align-items: center;
+ height: 24px;
+ align-self: center;
+}
+
+.chat-input-file-btn:hover {
+ color: var(--text-normal);
+}
+
+.chat-input-form textarea {
+ flex: 1;
+ padding: 11px 0;
+ background-color: transparent;
+ border: none;
+ color: var(--text-normal);
+ font-size: 16px;
+ font-family: inherit;
+ height: 44px;
+ resize: none;
+ overflow: hidden;
+ line-height: 1.375rem;
+ box-sizing: border-box;
+}
+
+.chat-input-form textarea:focus {
+ outline: none;
+}
+
+.chat-input-form textarea::placeholder {
+ color: #72767d;
+}
+
+.chat-input-icons {
+ display: flex;
+ align-items: center;
+ padding: 0 0 0 10px;
+ align-self: center;
+ height: 100%;
+}
+
+.chat-input-icon-btn {
+ background: none;
+ border: none;
+ color: #b9bbbe;
+ cursor: pointer;
+ padding: 4px;
+ margin-left: 4px;
+ display: flex;
+ align-items: center;
+}
+
+.chat-input-icon-btn:hover {
+ color: var(--text-normal);
+}
+
+/* Link Previews */
+.link-preview {
+ display: flex;
+ background-color: #2f3136;
+ border-left: 4px solid #202225;
+ border-radius: 4px;
+ padding: 10px;
+ margin-top: 8px;
+ max-width: 520px;
+ gap: 16px;
+}
+
+.preview-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ min-width: 0;
+}
+
+.preview-site-name {
+ font-size: 12px;
+ color: #b9bbbe;
+ margin-bottom: 4px;
+}
+
+.preview-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #00b0f4;
+ text-decoration: none;
+ margin-bottom: 4px;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.preview-title:hover {
+ text-decoration: underline;
+}
+
+.preview-description {
+ font-size: 14px;
+ color: #dcddde;
+ line-height: 1.4;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.preview-image-container {
+ flex-shrink: 0;
+ position: relative;
+}
+
+.preview-image {
+ max-width: 150px;
+ max-height: 150px;
+ border-radius: 4px;
+ object-fit: cover;
+}
+
+.play-icon {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: white;
+ background: rgba(0, 0, 0, 0.6);
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+}
+
+.youtube-preview {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+}
+
+.youtube-preview .preview-image-container {
+ width: 100%;
+ max-width: 400px;
+ position: relative;
+}
+
+.youtube-preview .preview-image {
+ width: 100%;
+ max-width: 100%;
+ max-height: none;
+ aspect-ratio: 16 / 9;
+}
+
+.youtube-video-wrapper {
+ margin-top: 8px;
+ position: relative;
+ width: 100%;
+ max-width: 560px;
+ /* Standard YouTube embed width or max for chat */
+ padding-bottom: 56.25%;
+ /* 16:9 Aspect Ratio */
+ height: 0;
+ overflow: hidden;
+ border-radius: 4px;
+ background-color: black;
+}
+
+.youtube-video-wrapper iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
}
\ No newline at end of file
diff --git a/Frontend/Electron/src/pages/Login.jsx b/Frontend/Electron/src/pages/Login.jsx
index c05efbe..eb0879f 100644
--- a/Frontend/Electron/src/pages/Login.jsx
+++ b/Frontend/Electron/src/pages/Login.jsx
@@ -42,11 +42,20 @@ const Login = () => {
throw new Error(verifyData.error || 'Login failed');
}
- console.log('Login verified');
+ console.log('Login verified. Response data:', verifyData);
+
if (verifyData.userId) {
+ console.log('Saving userId to localStorage:', verifyData.userId);
localStorage.setItem('userId', verifyData.userId);
+ } else {
+ console.error('MISSING USERID IN VERIFY RESPONSE!', verifyData);
}
+
localStorage.setItem('username', username);
+
+ // Verify immediate read back
+ console.log('Immediate localStorage read check:', localStorage.getItem('userId'));
+
navigate('/chat');
} catch (err) {
console.error('Login error:', err);
diff --git a/Frontend/Electron/src/pages/Register.jsx b/Frontend/Electron/src/pages/Register.jsx
index 0a34e64..15b51b5 100644
--- a/Frontend/Electron/src/pages/Register.jsx
+++ b/Frontend/Electron/src/pages/Register.jsx
@@ -18,7 +18,7 @@ const Register = () => {
// 1. Generate Salt and Master Key (MK)
const salt = await window.cryptoAPI.randomBytes(16);
- const mk = await window.cryptoAPI.randomBytes(16); // 128-bit MK
+ const mk = await window.cryptoAPI.randomBytes(32); // 256-bit MK for AES-256
console.log('Generated Salt and MK');