aboutsummaryrefslogtreecommitdiff
path: root/client/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'client/index.html')
-rw-r--r--client/index.html563
1 files changed, 563 insertions, 0 deletions
diff --git a/client/index.html b/client/index.html
new file mode 100644
index 0000000..941394f
--- /dev/null
+++ b/client/index.html
@@ -0,0 +1,563 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>JCHAT - JMAP Chat Client</title>
+ <style>
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ background-color: #f5f5f5;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .header {
+ background-color: #2c3e50;
+ color: white;
+ padding: 1rem 2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
+
+ .header h1 {
+ font-size: 1.5rem;
+ font-weight: 600;
+ }
+
+ .connection-status {
+ padding: 0.5rem 1rem;
+ border-radius: 20px;
+ font-size: 0.9rem;
+ }
+
+ .status-connected {
+ background-color: #27ae60;
+ }
+
+ .status-disconnected {
+ background-color: #e74c3c;
+ }
+
+ .status-connecting {
+ background-color: #f39c12;
+ }
+
+ .main-container {
+ display: flex;
+ flex: 1;
+ overflow: hidden;
+ }
+
+ .sidebar {
+ width: 300px;
+ background-color: white;
+ border-right: 1px solid #ddd;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .sidebar-header {
+ padding: 1rem;
+ background-color: #34495e;
+ color: white;
+ font-weight: 600;
+ }
+
+ .user-info {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1rem;
+ font-size: 0.9rem;
+ }
+
+ .user-settings-btn {
+ background: none;
+ border: none;
+ cursor: pointer;
+ padding: 0.25rem;
+ border-radius: 4px;
+ font-size: 1rem;
+ color: white;
+ }
+
+ .user-settings-btn:hover {
+ background: rgba(255,255,255,0.2);
+ }
+
+ .new-conversation-btn {
+ width: 100%;
+ padding: 0.75rem;
+ background: #3498db;
+ color: white;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 0.9rem;
+ font-weight: 500;
+ transition: background-color 0.2s;
+ }
+
+ .new-conversation-btn:hover {
+ background: #2980b9;
+ }
+
+ /* Modal Styles */
+ .modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0,0,0,0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ }
+
+ .modal-content {
+ background: white;
+ padding: 2rem;
+ border-radius: 12px;
+ min-width: 400px;
+ max-width: 500px;
+ }
+
+ .modal-content h3 {
+ margin-top: 0;
+ margin-bottom: 1.5rem;
+ color: #333;
+ }
+
+ .modal-content label {
+ display: block;
+ margin-bottom: 1rem;
+ font-weight: 500;
+ color: #555;
+ }
+
+ .modal-content input,
+ .modal-content textarea {
+ width: 100%;
+ padding: 0.75rem;
+ border: 1px solid #ddd;
+ border-radius: 6px;
+ margin-top: 0.25rem;
+ font-size: 0.9rem;
+ }
+
+ .modal-content textarea {
+ resize: vertical;
+ min-height: 80px;
+ }
+
+ .modal-buttons {
+ display: flex;
+ gap: 1rem;
+ justify-content: flex-end;
+ margin-top: 1.5rem;
+ }
+
+ .modal-buttons button {
+ padding: 0.75rem 1.5rem;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 0.9rem;
+ font-weight: 500;
+ }
+
+ .modal-buttons button:first-child {
+ background: #4f46e5;
+ color: white;
+ }
+
+ .modal-buttons button:first-child:hover {
+ background: #3730a3;
+ }
+
+ .modal-buttons button:last-child {
+ background: #f3f4f6;
+ color: #374151;
+ }
+
+ .modal-buttons button:last-child:hover {
+ background: #e5e7eb;
+ }
+
+ .conversation-list {
+ flex: 1;
+ overflow-y: auto;
+ }
+
+ .conversation-item {
+ padding: 1rem;
+ border-bottom: 1px solid #eee;
+ cursor: pointer;
+ transition: background-color 0.2s;
+ }
+
+ .conversation-item:hover {
+ background-color: #f8f9fa;
+ }
+
+ .conversation-item.active {
+ background-color: #3498db;
+ color: white;
+ }
+
+ .conversation-title {
+ font-weight: 600;
+ margin-bottom: 0.25rem;
+ }
+
+ .conversation-preview {
+ font-size: 0.9rem;
+ color: #666;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .conversation-item.active .conversation-preview {
+ color: #ecf0f1;
+ }
+
+ .conversation-meta {
+ font-size: 0.8rem;
+ color: #999;
+ margin-top: 0.25rem;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .conversation-item.active .conversation-meta {
+ color: #bdc3c7;
+ }
+
+ .chat-area {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ background-color: white;
+ }
+
+ .chat-header {
+ padding: 1rem 2rem;
+ background-color: white;
+ border-bottom: 1px solid #ddd;
+ font-weight: 600;
+ }
+
+ .messages-container {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .message {
+ display: flex;
+ gap: 0.75rem;
+ max-width: 70%;
+ }
+
+ .message.own {
+ align-self: flex-end;
+ flex-direction: row-reverse;
+ }
+
+ .message-avatar {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ background-color: #3498db;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-weight: 600;
+ font-size: 0.9rem;
+ flex-shrink: 0;
+ }
+
+ .message-content {
+ background-color: #f8f9fa;
+ padding: 0.75rem 1rem;
+ border-radius: 18px;
+ position: relative;
+ }
+
+ .message.own .message-content {
+ background-color: #3498db;
+ color: white;
+ }
+
+ .message-sender {
+ font-weight: 600;
+ font-size: 0.9rem;
+ margin-bottom: 0.25rem;
+ }
+
+ .message.own .message-sender {
+ display: none;
+ }
+
+ .message-text {
+ line-height: 1.4;
+ }
+
+ .message-time {
+ font-size: 0.8rem;
+ color: #999;
+ margin-top: 0.25rem;
+ }
+
+ .message.own .message-time {
+ color: rgba(255,255,255,0.8);
+ }
+
+ .message-input-area {
+ padding: 1rem 2rem;
+ background-color: white;
+ border-top: 1px solid #ddd;
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ }
+
+ .message-input {
+ flex: 1;
+ padding: 0.75rem 1rem;
+ border: 1px solid #ddd;
+ border-radius: 24px;
+ font-size: 1rem;
+ outline: none;
+ resize: none;
+ max-height: 120px;
+ min-height: 44px;
+ }
+
+ .message-input:focus {
+ border-color: #3498db;
+ }
+
+ .send-button {
+ background-color: #3498db;
+ color: white;
+ border: none;
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: background-color 0.2s;
+ }
+
+ .send-button:hover:not(:disabled) {
+ background-color: #2980b9;
+ }
+
+ .send-button:disabled {
+ background-color: #bdc3c7;
+ cursor: not-allowed;
+ }
+
+ .empty-state {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: #666;
+ }
+
+ .empty-state h3 {
+ margin-bottom: 0.5rem;
+ }
+
+ .loading {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 2rem;
+ color: #666;
+ }
+
+ .error {
+ background-color: #e74c3c;
+ color: white;
+ padding: 1rem;
+ margin: 1rem;
+ border-radius: 6px;
+ }
+
+ /* Mobile responsive */
+ @media (max-width: 768px) {
+ .main-container {
+ flex-direction: column;
+ }
+
+ .sidebar {
+ width: 100%;
+ height: 200px;
+ }
+
+ .message {
+ max-width: 85%;
+ }
+ }
+ </style>
+</head>
+<body>
+ <div class="header">
+ <h1>JCHAT Client</h1>
+ <div class="connection-status status-disconnected" id="connectionStatus">
+ Disconnected
+ </div>
+ </div>
+
+ <div class="main-container">
+ <div class="sidebar">
+ <div class="sidebar-header">
+ <div class="user-info">
+ <span id="currentUser">Anonymous User</span>
+ <button class="user-settings-btn" onclick="showUserSettings()" title="User Settings">⚙️</button>
+ </div>
+ <button class="new-conversation-btn" onclick="showNewConversationDialog()">+ New Conversation</button>
+ </div>
+ <div class="conversation-list" id="conversationList">
+ <div class="loading">Loading conversations...</div>
+ </div>
+ </div>
+
+ <div class="chat-area">
+ <div class="chat-header" id="chatHeader">
+ Select a conversation
+ </div>
+ <div class="messages-container" id="messagesContainer">
+ <div class="empty-state">
+ <h3>Welcome to JCHAT</h3>
+ <p>Select a conversation to start chatting</p>
+ </div>
+ </div>
+ <div class="message-input-area" id="messageInputArea" style="display: none;">
+ <textarea
+ class="message-input"
+ id="messageInput"
+ placeholder="Type a message..."
+ rows="1"></textarea>
+ <button class="send-button" id="sendButton" disabled>
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
+ <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
+ </svg>
+ </button>
+ </div>
+ </div>
+ </div>
+
+ <!-- Authentication Modals -->
+ <!-- Login Modal -->
+ <div class="modal" id="loginModal" style="display: none;">
+ <div class="modal-content">
+ <h3>Log In</h3>
+ <div id="loginError" style="color: #e74c3c; margin-bottom: 1rem; display: none;"></div>
+ <label>
+ Email:
+ <input type="email" id="loginEmail" placeholder="Enter your email" required>
+ </label>
+ <label>
+ Password:
+ <input type="password" id="loginPassword" placeholder="Enter your password" required>
+ </label>
+ <div class="modal-buttons">
+ <button onclick="performLogin()">Log In</button>
+ <button onclick="showRegisterModal()">Register Instead</button>
+ <button onclick="closeModal('loginModal')">Cancel</button>
+ </div>
+ </div>
+ </div>
+
+ <!-- Register Modal -->
+ <div class="modal" id="registerModal" style="display: none;">
+ <div class="modal-content">
+ <h3>Create Account</h3>
+ <div id="registerError" style="color: #e74c3c; margin-bottom: 1rem; display: none;"></div>
+ <label>
+ Email:
+ <input type="email" id="registerEmail" placeholder="Enter your email" required>
+ </label>
+ <label>
+ Display Name:
+ <input type="text" id="registerDisplayName" placeholder="Enter your display name" required>
+ </label>
+ <label>
+ Password:
+ <input type="password" id="registerPassword" placeholder="Create a password (min 8 characters)" required>
+ </label>
+ <label>
+ Confirm Password:
+ <input type="password" id="registerConfirmPassword" placeholder="Confirm your password" required>
+ </label>
+ <div class="modal-buttons">
+ <button onclick="performRegistration()">Create Account</button>
+ <button onclick="showLoginModal()">Log In Instead</button>
+ <button onclick="closeModal('registerModal')">Cancel</button>
+ </div>
+ </div>
+ </div>
+
+ <!-- User Settings Modal -->
+ <div class="modal" id="userSettingsModal" style="display: none;">
+ <div class="modal-content">
+ <h3>User Settings</h3>
+ <label>
+ Display Name:
+ <input type="text" id="userDisplayName" placeholder="Enter your name">
+ </label>
+ <div class="modal-buttons">
+ <button onclick="saveUserSettings()">Save</button>
+ <button onclick="closeModal('userSettingsModal')">Cancel</button>
+ </div>
+ </div>
+ </div>
+
+ <!-- New Conversation Modal -->
+ <div class="modal" id="newConversationModal" style="display: none;">
+ <div class="modal-content">
+ <h3>New Conversation</h3>
+ <label>
+ Conversation Title:
+ <input type="text" id="newConversationTitle" placeholder="Enter conversation title">
+ </label>
+ <label>
+ Description (optional):
+ <textarea id="newConversationDescription" placeholder="Conversation description"></textarea>
+ </label>
+ <div class="modal-buttons">
+ <button onclick="createNewConversation()">Create</button>
+ <button onclick="closeModal('newConversationModal')">Cancel</button>
+ </div>
+ </div>
+ </div>
+
+ <script src="config.js"></script>
+ <script src="jmap-client.js"></script>
+ <script src="app.js"></script>
+</body>
+</html>