Update src/templates/chat.html
This commit is contained in:
@@ -7,54 +7,60 @@
|
|||||||
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
||||||
<meta http-equiv="X-Frame-Options" content="DENY">
|
<meta http-equiv="X-Frame-Options" content="DENY">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='stylesheet.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='stylesheet.css') }}">
|
||||||
|
<link rel="stylesheet" href="../static/stylesheet.css">
|
||||||
<link rel="icon" type="image/png" href="{{ url_for('static', filename='favicon.png') }}">
|
<link rel="icon" type="image/png" href="{{ url_for('static', filename='favicon.png') }}">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@4.7.2/dist/socket.io.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@4.7.2/dist/socket.io.min.js"></script>
|
||||||
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
<script src="{{ url_for('static', filename='script.js') }}"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="overflow-y: auto;">
|
||||||
<div class="chat-container">
|
<div class="chat-container">
|
||||||
<div class="chat-header">
|
<div class="chat-header" style="padding: 0.75rem 1rem;">
|
||||||
<div class="header-content">
|
<div class="header-content" style="flex-wrap: wrap; gap: 0.5rem;">
|
||||||
<div class="logo">
|
<div class="logo" style="font-size: clamp(1.25rem, 4vw, 1.5rem);">
|
||||||
<a href="/" style="text-decoration: none; font-weight: inherit; font-style: inherit; color: inherit;">
|
<a href="/" style="text-decoration: none; font-weight: inherit; font-style: inherit; color: inherit;">
|
||||||
ByteChat
|
ByteChat
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="encryption-badge" id="encryptionBadge">
|
<div class="encryption-badge" id="encryptionBadge" style="font-size: clamp(0.75rem, 3vw, 0.85rem); padding: 0.4rem 0.8rem;">
|
||||||
E2E Encrypted
|
E2E Encrypted
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Welcome Screen -->
|
<!-- Welcome Screen -->
|
||||||
<div id="welcomeScreen" class="welcome-screen">
|
<div id="welcomeScreen" class="welcome-screen" style="padding: 1rem;">
|
||||||
<h1 class="welcome-title">End-to-End Encrypted Chat</h1>
|
<h1 class="welcome-title" style="font-size: clamp(1.75rem, 8vw, 3rem); margin-bottom: 0.75rem;">Anonymous Chatting</h1>
|
||||||
<p class="welcome-subtitle">
|
<p class="welcome-subtitle" style="font-size: clamp(0.9rem, 3.5vw, 1.1rem); margin-bottom: 2rem; padding: 0 0.5rem;">
|
||||||
Your messages are encrypted in your browser before being sent.
|
If you are coming from the "ngrok" link. Then you probably saw the warning page. That this Page may be maillicious.
|
||||||
Messages are stored temporarily in memory and automatically deleted after 256 messages.
|
We are focused on privacy and encrypted messaging. We do not serve any harmful code. We are
|
||||||
|
<a style="text-decoration: none; color:#00ff88;font-style: inherit; font-style: italic;" href="https://rattatwinko.servecounterstrike.com/gitea/rattatwinko/bytechat"
|
||||||
|
>OSS</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="room-section">
|
<div class="room-section" style="width: 100%; max-width: 500px;">
|
||||||
<div class="room-input-container">
|
<div class="room-input-container" style="flex-direction: column; gap: 0.75rem; width: 100%;">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="room-input"
|
class="room-input"
|
||||||
id="roomInput"
|
id="roomInput"
|
||||||
placeholder="Enter room ID (leave blank for new room)"
|
placeholder="Enter room ID"
|
||||||
maxlength="32"
|
maxlength="32"
|
||||||
pattern="[a-zA-Z0-9\-_]+"
|
pattern="[a-zA-Z0-9\-_]+"
|
||||||
title="Only letters, numbers, hyphens and underscores allowed">
|
title="Only letters, numbers, hyphens and underscores allowed"
|
||||||
|
style="width: 100%; min-width: unset; font-size: clamp(0.9rem, 4vw, 1rem);">
|
||||||
<input type="password"
|
<input type="password"
|
||||||
class="room-input"
|
class="room-input"
|
||||||
id="roomPasswordInput"
|
id="roomPasswordInput"
|
||||||
placeholder="Optional: Channel Password"
|
placeholder="Optional: Channel Password"
|
||||||
style="max-width: 220px;"
|
|
||||||
maxlength="128"
|
maxlength="128"
|
||||||
autocomplete="new-password">
|
autocomplete="new-password"
|
||||||
<button class="btn" id="joinRoomBtn" aria-label="Join existing room">Join Room</button>
|
style="width: 100%; min-width: unset; max-width: none; font-size: clamp(0.9rem, 4vw, 1rem); overflow: hidden; text-overflow: ellipsis;">
|
||||||
<button class="btn btn-secondary" id="createRoomBtn" aria-label="Create new room">Create New Room</button>
|
<div style="display: flex; gap: 0.75rem; flex-wrap: wrap;">
|
||||||
|
<button class="btn" id="joinRoomBtn" aria-label="Join existing room" style="flex: 1; min-width: 120px; font-size: clamp(0.85rem, 3.5vw, 1rem); padding: 0.6rem 1rem;">Join Room</button>
|
||||||
|
<button class="btn btn-secondary" id="createRoomBtn" aria-label="Create new room" style="flex: 1; min-width: 120px; font-size: clamp(0.85rem, 3.5vw, 1rem); padding: 0.6rem 1rem;">Create New Room</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-text" id="statusText">
|
</div>
|
||||||
|
<div class="status-text" id="statusText" style="font-size: clamp(0.8rem, 3vw, 0.9rem);">
|
||||||
<div class="loading-message">
|
<div class="loading-message">
|
||||||
<div class="loading-spinner"></div>
|
<div class="loading-spinner"></div>
|
||||||
<span aria-live="polite">Initializing encryption keys...</span>
|
<span aria-live="polite">Initializing encryption keys...</span>
|
||||||
@@ -62,53 +68,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="feature-list">
|
<div class="feature-list" style="grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); gap: 1rem; margin-top: 1.5rem; width: 100%;">
|
||||||
<div class="feature-item">
|
<div class="feature-item" style="padding: 1.25rem;">
|
||||||
<div class="feature-icon" role="img" aria-label="Security">🔐</div>
|
<div class="feature-icon" role="img" aria-label="Security" style="font-size: clamp(1.5rem, 5vw, 2rem);">🔐</div>
|
||||||
<div class="feature-title">End-to-End Encryption</div>
|
<div class="feature-title" style="font-size: clamp(0.95rem, 3.5vw, 1.1rem);">End-to-End Encryption</div>
|
||||||
<div class="feature-desc">Messages are encrypted with AES-256 in your browser. The server never sees your messages.</div>
|
<div class="feature-desc" style="font-size: clamp(0.8rem, 3vw, 0.9rem);">Messages are encrypted with AES-256 in your browser. The server never sees your messages.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature-item">
|
<div class="feature-item" style="padding: 1.25rem;">
|
||||||
<div class="feature-icon" role="img" aria-label="Ephemeral">⚡</div>
|
<div class="feature-icon" role="img" aria-label="Real-time" style="font-size: clamp(1.5rem, 5vw, 2rem);">🌐</div>
|
||||||
<div class="feature-title">Ephemeral Messages</div>
|
<div class="feature-title" style="font-size: clamp(0.95rem, 3.5vw, 1.1rem);">Real-time Chat</div>
|
||||||
<div class="feature-desc">Only 256 messages stored in memory. Older messages are automatically deleted.</div>
|
<div class="feature-desc" style="font-size: clamp(0.8rem, 3vw, 0.9rem);">Instant messaging with WebSocket technology for immediate message delivery.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature-item">
|
<div class="feature-item" style="padding: 1.25rem;">
|
||||||
<div class="feature-icon" role="img" aria-label="Real-time">🌐</div>
|
<div class="feature-icon" role="img" aria-label="Anonymous" style="font-size: clamp(1.5rem, 5vw, 2rem);">🎭</div>
|
||||||
<div class="feature-title">Real-time Chat</div>
|
<div class="feature-title" style="font-size: clamp(0.95rem, 3.5vw, 1.1rem);">Anonymous Users</div>
|
||||||
<div class="feature-desc">Instant messaging with WebSocket technology for immediate message delivery.</div>
|
<div class="feature-desc" style="font-size: clamp(0.8rem, 3vw, 0.9rem);">Each session gets a new random UUID. No registration or personal info required.</div>
|
||||||
</div>
|
|
||||||
<div class="feature-item">
|
|
||||||
<div class="feature-icon" role="img" aria-label="Anonymous">🎭</div>
|
|
||||||
<div class="feature-title">Anonymous Users</div>
|
|
||||||
<div class="feature-desc">Each session gets a new random UUID. No registration or personal info required.</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Chat Screen -->
|
<!-- Chat Screen -->
|
||||||
<div id="chatScreen" style="display: none;" class="chat-screen">
|
<div id="chatScreen" style="display: none;" class="chat-screen">
|
||||||
<div class="room-info" id="roomInfo" style="display: none;">
|
<div class="room-info" id="roomInfo" style="display: none; padding: 0.6rem 0.75rem; flex-wrap: wrap; gap: 0.5rem;">
|
||||||
<div class="room-details">
|
<div class="room-details" style="min-width: auto; flex: 1;">
|
||||||
<span>Room: <strong id="currentRoomId"></strong></span>
|
<span style="font-size: clamp(0.75rem, 3vw, 0.85rem);">Room: <strong id="currentRoomId"></strong></span>
|
||||||
<span id="messageCounter">Messages: 0/256</span>
|
<span id="messageCounter" style="font-size: clamp(0.75rem, 3vw, 0.85rem);">Messages: 0/256</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="room-details">
|
<div class="room-details" style="min-width: auto; flex: 1;">
|
||||||
<span id="userCounter">Users: 0</span>
|
<span id="userCounter" style="font-size: clamp(0.75rem, 3vw, 0.85rem);">Users: 0</span>
|
||||||
<span id="encryptionStatus">🔐 Encrypted</span>
|
<span id="encryptionStatus" style="font-size: clamp(0.75rem, 3vw, 0.85rem);">🔐 Encrypted</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- wrapper for scroll -->
|
<!-- wrapper for scroll -->
|
||||||
<div class="messages-wrapper" id="messagesWrapper">
|
<div class="messages-wrapper" id="messagesWrapper" style="padding: 0.75rem; padding-bottom: 80px; flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; scroll-behavior: smooth;">
|
||||||
<div class="messages-container" id="messagesContainer" role="log" aria-live="polite" aria-label="Chat messages">
|
<div class="messages-container" id="messagesContainer" role="log" aria-live="polite" aria-label="Chat messages">
|
||||||
<!-- Messages will be inserted here -->
|
<!-- Messages will be inserted here -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-section" id="inputSection" style="display: none;">
|
<div class="input-section" id="inputSection" style="display: none; padding: 0.6rem 0.75rem; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; background: rgba(20, 20, 20, 0.98); backdrop-filter: blur(10px); border-top: 1px solid #333; box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3);">
|
||||||
<div class="input-container">
|
<div class="input-container" style="gap: 0.4rem; max-width: 100%;">
|
||||||
<label for="messageInput" class="visually-hidden">Type your message</label>
|
<label for="messageInput" class="visually-hidden">Type your message</label>
|
||||||
<textarea
|
<textarea
|
||||||
class="message-input"
|
class="message-input"
|
||||||
@@ -118,9 +119,13 @@
|
|||||||
disabled
|
disabled
|
||||||
maxlength="4000"
|
maxlength="4000"
|
||||||
aria-label="Type your message"
|
aria-label="Type your message"
|
||||||
|
style="font-size: clamp(0.9rem, 4vw, 1rem); padding: 0.6rem 0.8rem; border-radius: 10px; resize: none; max-height: 120px; min-height: 44px; font-size: 16px; -webkit-appearance: none;"
|
||||||
|
autocomplete="off"
|
||||||
|
autocapitalize="sentences"
|
||||||
|
spellcheck="true"
|
||||||
></textarea>
|
></textarea>
|
||||||
<button class="send-button" id="sendButton" disabled aria-label="Send message">
|
<button class="send-button" id="sendButton" disabled aria-label="Send message" style="width: 40px; height: 40px; flex-shrink: 0; -webkit-tap-highlight-color: transparent;">
|
||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||||
<path d="m22 2-7 20-4-9-9-4 20-7z"/>
|
<path d="m22 2-7 20-4-9-9-4 20-7z"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
@@ -128,10 +133,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="security-indicator" id="securityIndicator" style="display: none;">
|
<div class="security-indicator" id="securityIndicator" style="display: none; bottom: calc(0.75rem + 80px); right: 15px; padding: 0.4rem 0.8rem; font-size: clamp(0.7rem, 3vw, 0.8rem); z-index: 999;">
|
||||||
🔒 End-to-End Encrypted
|
🔒 End-to-End Encrypted
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Mobile keyboard handling
|
||||||
|
let initialViewportHeight = window.innerHeight;
|
||||||
|
|
||||||
|
function adjustForKeyboard() {
|
||||||
|
const currentHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
|
||||||
|
const diff = initialViewportHeight - currentHeight;
|
||||||
|
const messagesWrapper = document.getElementById('messagesWrapper');
|
||||||
|
|
||||||
|
if (diff > 150) { // Keyboard is likely open
|
||||||
|
if (messagesWrapper) {
|
||||||
|
messagesWrapper.style.paddingBottom = '100px';
|
||||||
|
// Scroll to bottom when keyboard opens
|
||||||
|
setTimeout(() => {
|
||||||
|
messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (messagesWrapper) {
|
||||||
|
messagesWrapper.style.paddingBottom = '80px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for viewport changes (keyboard open/close)
|
||||||
|
if (window.visualViewport) {
|
||||||
|
window.visualViewport.addEventListener('resize', adjustForKeyboard);
|
||||||
|
} else {
|
||||||
|
window.addEventListener('resize', adjustForKeyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus handling for textarea
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const messageInput = document.getElementById('messageInput');
|
||||||
|
if (messageInput) {
|
||||||
|
messageInput.addEventListener('focus', function() {
|
||||||
|
setTimeout(adjustForKeyboard, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
messageInput.addEventListener('blur', function() {
|
||||||
|
setTimeout(adjustForKeyboard, 300);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user