From b8332666642501fcc4399208eaaf1654fba1ed19 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Fri, 28 Nov 2025 02:28:52 +0700 Subject: [PATCH] more refactor in frontend javascript --- web/css/index.css | 1256 +++++++++++++++++++++ web/index.html | 2384 +--------------------------------------- web/js/avatar.js | 72 ++ web/js/chats.js | 184 ++++ web/js/connection.js | 128 +++ web/js/deletemodal.js | 19 + web/js/index.js | 126 +++ web/js/login.js | 94 ++ web/js/messages.js | 245 +++++ web/js/profilemodal.js | 37 + web/js/register.js | 54 + web/js/search.js | 75 ++ web/js/theme.js | 10 + web/js/window.js | 27 + 14 files changed, 2345 insertions(+), 2366 deletions(-) create mode 100644 web/css/index.css create mode 100644 web/js/avatar.js create mode 100644 web/js/chats.js create mode 100644 web/js/connection.js create mode 100644 web/js/deletemodal.js create mode 100644 web/js/index.js create mode 100644 web/js/login.js create mode 100644 web/js/messages.js create mode 100644 web/js/profilemodal.js create mode 100644 web/js/register.js create mode 100644 web/js/search.js create mode 100644 web/js/theme.js create mode 100644 web/js/window.js diff --git a/web/css/index.css b/web/css/index.css new file mode 100644 index 0000000..96592dd --- /dev/null +++ b/web/css/index.css @@ -0,0 +1,1256 @@ +:root { + --bg-primary: #ffffff; + --bg-secondary: #f8f9fa; + --bg-tertiary: #e9ecef; + --text-primary: #2c3e50; + --text-secondary: #7f8c8d; + --border-color: #e9ecef; + --primary-color: #3498db; + --primary-hover: #2980b9; + --success-color: #27ae60; + --error-color: #e74c3c; + --warning-color: #f39c12; + --shadow: rgba(0, 0, 0, 0.1); +} + +[data-theme="dark"] { + --bg-primary: #1a1a1a; + --bg-secondary: #2d2d2d; + --bg-tertiary: #3d3d3d; + --text-primary: #ffffff; + --text-secondary: #b0b0b0; + --border-color: #444444; + --primary-color: #2980b9; + --primary-hover: #3498db; + --success-color: #2ecc71; + --error-color: #e74c3c; + --warning-color: #f39c12; + --shadow: rgba(0, 0, 0, 0.3); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + height: 100vh; + overflow: hidden; + transition: background 0.3s ease; +} + +[data-theme="dark"] body { + background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%); +} + +/* Auth Container */ +.auth-container { + width: 100%; + max-width: 400px; + margin: 0 auto; + background: var(--bg-primary); + padding: 30px 20px; + border-radius: 0; + box-shadow: 0 0 0 rgba(0, 0, 0, 0); + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + transition: all 0.3s ease; +} + +.auth-tabs { + display: flex; + margin-bottom: 25px; + border-bottom: 1px solid var(--border-color); +} + +.auth-tab { + flex: 1; + padding: 15px 10px; + text-align: center; + cursor: pointer; + border-bottom: 3px solid transparent; + transition: all 0.3s ease; + font-size: 14px; + color: var(--text-primary); +} + +.auth-tab.active { + border-bottom-color: var(--primary-color); + color: var(--primary-color); + font-weight: 600; +} + +.auth-form { + display: none; +} + +.auth-form.active { + display: block; +} + +.form-group { + margin-bottom: 15px; +} + +.form-group label { + display: block; + margin-bottom: 6px; + font-weight: 500; + color: var(--text-primary); + font-size: 14px; +} + +.form-control { + width: 100%; + padding: 12px 15px; + border: 2px solid var(--border-color); + border-radius: 8px; + font-size: 16px; + outline: none; + transition: border-color 0.3s ease; + background: var(--bg-primary); + color: var(--text-primary); +} + +.form-control:focus { + border-color: var(--primary-color); +} + +.btn { + width: 100%; + padding: 12px; + background: linear-gradient( + 135deg, + var(--primary-color), + var(--primary-hover) + ); + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 16px; + font-weight: 600; + transition: all 0.3s ease; +} + +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4); +} + +.alert { + padding: 10px 12px; + border-radius: 6px; + margin-bottom: 15px; + display: none; + font-size: 14px; +} + +.alert-success { + background: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.alert-error { + background: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +/* Chat Container */ +.chat-container { + width: 100%; + height: 100vh; + background: var(--bg-primary); + display: none; + flex-direction: column; + transition: background 0.3s ease; +} + +/* Mobile Header */ +.mobile-header { + display: none; + padding: 15px; + background: var(--bg-secondary); + color: var(--text-primary); + align-items: center; + justify-content: space-between; + border-bottom: 1px solid var(--border-color); + position: sticky; + top: 0; + z-index: 100; +} + +.menu-btn { + background: none; + border: none; + color: var(--text-primary); + font-size: 20px; + cursor: pointer; + padding: 5px; +} + +.mobile-title { + font-weight: 600; + font-size: 18px; +} + +.profile-header-btn { + background: none; + border: none; + cursor: pointer; + padding: 5px; + border-radius: 50%; + transition: background 0.3s ease; +} + +.profile-header-btn:hover { + background: var(--bg-tertiary); +} + +.profile-header-avatar { + width: 35px; + height: 35px; + border-radius: 50%; + object-fit: cover; + background: var(--bg-tertiary); + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + font-size: 14px; + font-weight: 600; +} + +.profile-header-avatar img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; +} + +.chats-panel { + width: 350px; + background: var(--bg-secondary); + color: var(--text-primary); + display: flex; + flex-direction: column; + height: 100vh; + transition: transform 0.3s ease; + border-right: 1px solid var(--border-color); +} + +.chats-header { + padding: 20px; + border-bottom: 1px solid var(--border-color); + display: flex; + justify-content: space-between; + align-items: center; +} + +.chats-tabs { + display: flex; + border-bottom: 1px solid var(--border-color); +} + +.chat-tab { + flex: 1; + padding: 15px 10px; + text-align: center; + cursor: pointer; + border-bottom: 3px solid transparent; + transition: all 0.3s ease; + font-size: 14px; + color: var(--text-primary); +} + +.chat-tab.active { + border-bottom-color: var(--primary-color); + color: var(--primary-color); + font-weight: 600; +} + +.search-container { + padding: 15px; + border-bottom: 1px solid var(--border-color); + display: none; +} + +.search-input { + width: 100%; + padding: 10px 12px; + border: 1px solid var(--border-color); + border-radius: 20px; + background: var(--bg-tertiary); + color: var(--text-primary); + outline: none; + font-size: 14px; +} + +.search-input::placeholder { + color: var(--text-secondary); +} + +.search-results { + max-height: 300px; + overflow-y: auto; +} + +.chat-list { + list-style: none; + flex: 1; + overflow-y: auto; +} + +.chat-item { + padding: 12px 15px; + border-bottom: 1px solid var(--border-color); + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; +} + +.chat-item:hover { + background: var(--bg-tertiary); +} + +.chat-item.active { + background: var(--primary-color); + color: white; +} + +.chat-avatar { + width: 45px; + height: 45px; + border-radius: 50%; + margin-right: 12px; + object-fit: cover; + background: var(--bg-tertiary); + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + font-size: 18px; + flex-shrink: 0; +} + +.chat-avatar img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; +} + +.chat-info { + flex: 1; + min-width: 0; +} + +.chat-username { + font-weight: 600; + margin-bottom: 3px; + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.chat-phone { + font-size: 11px; + color: var(--text-secondary); + margin-bottom: 3px; +} + +.chat-last-message { + font-size: 12px; + color: var(--text-secondary); + opacity: 0.8; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.chat-meta { + display: flex; + flex-direction: column; + align-items: flex-end; + flex-shrink: 0; + margin-left: 10px; +} + +.chat-time { + font-size: 10px; + color: var(--text-secondary); + margin-bottom: 5px; +} + +.unread-badge { + background: var(--error-color); + color: white; + border-radius: 50%; + width: 18px; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: 600; +} + +.chat-panel { + flex: 1; + display: flex; + flex-direction: column; + background: var(--bg-primary); + height: 100vh; + position: relative; +} + +.chat-header { + padding: 12px 15px; + background: var(--bg-primary); + border-bottom: 1px solid var(--border-color); + display: flex; + justify-content: space-between; + align-items: center; + position: sticky; + top: 0; + z-index: 10; + min-height: 64px; +} + +.chat-header-info { + display: flex; + align-items: center; + flex: 1; +} + +.back-btn { + display: none; + background: none; + border: none; + font-size: 18px; + margin-right: 10px; + cursor: pointer; + color: var(--primary-color); +} + +.chat-header-avatar { + width: 40px; + height: 40px; + border-radius: 50%; + margin-right: 10px; + object-fit: cover; + background: var(--bg-tertiary); + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + font-size: 16px; + flex-shrink: 0; +} + +.chat-header-avatar img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; +} + +.chat-header-text { + display: flex; + flex-direction: column; + min-width: 0; + flex: 1; +} + +.chat-header-username { + font-weight: 600; + font-size: 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: var(--text-primary); +} + +.chat-header-phone { + font-size: 12px; + color: var(--text-secondary); +} + +.chat-messages { + flex: 1; + padding: 15px; + overflow-y: auto; + background: var(--bg-primary); + display: flex; + flex-direction: column; + min-height: 0; +} + +.message { + max-width: 85%; + margin: 8px 0; + padding: 12px 15px; + border-radius: 18px; + position: relative; + word-wrap: break-word; + overflow-wrap: break-word; + word-break: break-word; + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.incoming { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + align-self: flex-start; + border-bottom-left-radius: 5px; + box-shadow: 0 2px 5px var(--shadow); + color: var(--text-primary); +} + +.outgoing { + background: linear-gradient( + 135deg, + var(--primary-color), + var(--primary-hover) + ); + color: white; + align-self: flex-end; + margin-left: auto; + border-bottom-right-radius: 5px; + box-shadow: 0 2px 5px rgba(52, 152, 219, 0.3); +} + +.message-sender { + font-size: 11px; + font-weight: 600; + margin-bottom: 4px; + opacity: 0.8; +} + +.message-content { + margin: 6px 0; + line-height: 1.4; + font-size: 14px; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; +} + +.message-time { + font-size: 10px; + text-align: right; + opacity: 0.7; + margin-top: 4px; +} + +.chat-input-container { + position: sticky; + bottom: 0; + background: var(--bg-primary); + border-top: 1px solid var(--border-color); + padding: 15px; + z-index: 10; +} + +.chat-input-area { + display: flex; + gap: 10px; + align-items: flex-end; + max-height: 120px; +} + +.message-input { + flex: 1; + padding: 12px 15px; + border: 2px solid var(--border-color); + border-radius: 25px; + outline: none; + font-size: 14px; + transition: border-color 0.3s ease; + background: var(--bg-primary); + color: var(--text-primary); + resize: none; + min-height: 44px; + max-height: 100px; + font-family: inherit; + line-height: 1.4; +} + +.message-input:focus { + border-color: var(--primary-color); +} + +.send-button { + padding: 12px 20px; + background: linear-gradient( + 135deg, + var(--primary-color), + var(--primary-hover) + ); + color: white; + border: none; + border-radius: 25px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: all 0.3s ease; + flex-shrink: 0; + min-height: 44px; +} + +.send-button:hover:not(:disabled) { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4); +} + +.send-button:disabled { + background: var(--bg-tertiary); + color: var(--text-secondary); + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.system-message { + text-align: center; + color: var(--text-secondary); + font-style: italic; + margin: 10px 0; + font-size: 12px; + padding: 8px; + background: var(--bg-secondary); + border-radius: 10px; + align-self: center; + max-width: 80%; +} + +.empty-state { + text-align: center; + color: var(--text-secondary); + padding: 30px 15px; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.empty-state h3 { + margin-bottom: 8px; + font-weight: 300; + font-size: 16px; +} + +.empty-state p { + font-size: 14px; +} + +/* Стили для кнопки удаления сообщения */ +.message-actions { + position: absolute; + top: 5px; + right: 8px; + opacity: 0; + transition: opacity 0.3s ease; +} + +.message:hover .message-actions { + opacity: 1; +} + +.delete-btn { + background: none; + border: none; + color: var(--text-secondary); + cursor: pointer; + font-size: 14px; + padding: 4px; + border-radius: 3px; +} + +.delete-btn:hover { + background: rgba(0, 0, 0, 0.1); + color: var(--error-color); +} + +/* Стили для модального окна профиля */ +.profile-modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.profile-modal { + background: var(--bg-primary); + border-radius: 15px; + padding: 0; + max-width: 400px; + width: 90%; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + margin: 20px; + overflow: hidden; +} + +.profile-header { + background: linear-gradient( + 135deg, + var(--primary-color), + var(--primary-hover) + ); + padding: 30px 20px; + text-align: center; + color: white; + position: relative; +} + +.profile-avatar-large { + width: 100px; + height: 100px; + border-radius: 50%; + margin: 0 auto 15px; + background: rgba(255, 255, 255, 0.2); + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 36px; + font-weight: 600; + border: 4px solid white; + position: relative; + cursor: pointer; + transition: transform 0.3s ease; +} + +.profile-avatar-large:hover { + transform: scale(1.05); +} + +.profile-avatar-large img { + width: 100%; + height: 100%; + border-radius: 50%; + object-fit: cover; +} + +.avatar-upload-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.7); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.3s ease; + color: white; + font-size: 12px; + text-align: center; + padding: 10px; +} + +.profile-avatar-large:hover .avatar-upload-overlay { + opacity: 1; +} + +.profile-name { + font-size: 20px; + font-weight: 600; + margin-bottom: 5px; +} + +.profile-phone { + font-size: 14px; + opacity: 0.9; +} + +.profile-content { + padding: 25px; +} + +.profile-section { + margin-bottom: 25px; +} + +.profile-section-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 15px; + color: var(--text-primary); + display: flex; + align-items: center; + gap: 8px; +} + +.profile-section-title i { + font-size: 18px; +} + +.profile-info { + background: var(--bg-secondary); + border-radius: 10px; + padding: 15px; +} + +.info-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 0; + border-bottom: 1px solid var(--border-color); +} + +.info-item:last-child { + border-bottom: none; +} + +.info-label { + font-size: 14px; + color: var(--text-secondary); +} + +.info-value { + font-size: 14px; + color: var(--text-primary); + font-weight: 500; +} + +.profile-actions { + display: flex; + flex-direction: column; + gap: 12px; +} + +.profile-btn { + padding: 12px 16px; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 10px; +} + +.profile-btn-primary { + background: linear-gradient( + 135deg, + var(--primary-color), + var(--primary-hover) + ); + color: white; +} + +.profile-btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4); +} + +.profile-btn-danger { + background: var(--error-color); + color: white; +} + +.profile-btn-danger:hover { + background: #c0392b; + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(231, 76, 60, 0.4); +} + +.profile-btn-secondary { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +.profile-btn-secondary:hover { + background: var(--border-color); +} + +/* Стили для скрытого input file */ +.avatar-input { + display: none; +} + +/* Scrollbars */ +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: var(--bg-tertiary); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--text-secondary); +} + +/* Desktop Layout */ +.desktop-layout { + display: flex; + height: 100vh; + width: 100%; +} + +/* Connection status */ +.connection-status { + position: fixed; + top: 10px; + right: 10px; + padding: 8px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 600; + z-index: 1000; + transition: all 0.3s ease; +} + +.connection-status.connected { + background: var(--success-color); + color: white; +} + +.connection-status.disconnected { + background: var(--error-color); + color: white; +} + +.connection-status.connecting { + background: var(--warning-color); + color: white; +} + +/* Mobile Styles */ +@media (max-width: 768px) { + .auth-container { + max-width: 100%; + padding: 20px; + border-radius: 0; + } + + .desktop-layout { + position: relative; + height: 100%; + } + + .chats-panel { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + z-index: 100; + transform: translateX(-100%); + } + + .chats-panel.active { + transform: translateX(0); + } + + .chat-panel { + width: 100%; + height: 100vh; + } + + .mobile-header { + display: flex; + } + + .back-btn { + display: block; + } + + .message { + max-width: 90%; + margin: 6px 0; + } + + .modal { + margin: 15px; + } + + .modal-buttons { + flex-direction: column; + } + + .modal-btn { + width: 100%; + } + + .chat-input-container { + padding: 10px; + padding-bottom: max(10px, env(safe-area-inset-bottom)); + } + + .chat-input-area { + gap: 8px; + } + + .message-input { + padding: 10px 12px; + min-height: 44px; + font-size: 16px; + } + + .send-button { + padding: 10px 16px; + min-height: 44px; + font-size: 14px; + } + + .connection-status { + top: 60px; + right: 10px; + } +} + +@media (max-width: 480px) { + .auth-container { + padding: 15px; + } + + .auth-tab { + padding: 12px 8px; + font-size: 13px; + } + + .form-control { + padding: 10px 12px; + font-size: 16px; + } + + .btn { + padding: 12px; + } + + .chat-header { + padding: 10px 12px; + min-height: 60px; + } + + .chat-messages { + padding: 10px; + padding-bottom: 70px; + } + + .message { + padding: 10px 12px; + max-width: 95%; + margin: 4px 0; + } + + .message-content { + font-size: 14px; + } + + .chat-input-container { + padding: 8px; + padding-bottom: max(8px, env(safe-area-inset-bottom)); + } + + .message-input { + padding: 8px 12px; + font-size: 16px; + } + + .send-button { + padding: 8px 14px; + font-size: 14px; + } + + .mobile-title { + font-size: 16px; + } + + .chat-header-username { + font-size: 15px; + } +} + +/* Very small screens */ +@media (max-width: 320px) { + .chat-avatar { + width: 40px; + height: 40px; + font-size: 16px; + margin-right: 8px; + } + + .chat-header-avatar { + width: 35px; + height: 35px; + font-size: 14px; + } + + .chat-item { + padding: 10px 12px; + } + + .chat-input-area { + gap: 6px; + } + + .message-input { + padding: 8px 10px; + } + + .send-button { + padding: 8px 12px; + min-width: 60px; + } +} + +/* Safe area support for notches */ +@supports (padding: max(0px)) { + .chat-input-container { + padding-bottom: max(15px, env(safe-area-inset-bottom)); + } + + @media (max-width: 768px) { + .chat-input-container { + padding-bottom: max(10px, env(safe-area-inset-bottom)); + } + } + + @media (max-width: 480px) { + .chat-input-container { + padding-bottom: max(8px, env(safe-area-inset-bottom)); + } + } +} + +/* Prevent body scroll when modal is open */ +body.modal-open { + overflow: hidden; +} + +/* Theme transition */ +* { + transition: + background-color 0.3s ease, + color 0.3s ease, + border-color 0.3s ease; +} + +/* Ensure messages are always fully visible */ +.chat-messages-container { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + position: relative; +} + +/* Стили для модального окна удаления */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; +} + +.modal { + background: var(--bg-primary); + border-radius: 10px; + padding: 20px; + max-width: 350px; + width: 90%; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); + margin: 20px; +} + +.modal h3 { + margin-bottom: 12px; + color: var(--text-primary); + font-size: 18px; +} + +.modal p { + margin-bottom: 18px; + color: var(--text-secondary); + font-size: 14px; +} + +.modal-buttons { + display: flex; + gap: 8px; + justify-content: flex-end; + flex-wrap: wrap; +} + +.modal-btn { + padding: 8px 16px; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 14px; +} + +.modal-btn-cancel { + background: var(--bg-tertiary); + color: var(--text-primary); +} + +.modal-btn-cancel:hover { + background: var(--border-color); +} + +.modal-btn-delete { + background: var(--error-color); + color: white; +} + +.modal-btn-delete:hover { + background: #c0392b; +} + +.modal-btn-delete-for-me { + background: var(--primary-color); + color: white; +} + +.modal-btn-delete-for-me:hover { + background: var(--primary-hover); +} diff --git a/web/index.html b/web/index.html index a2b70c7..28caca9 100644 --- a/web/index.html +++ b/web/index.html @@ -3,1187 +3,8 @@ + Secure Chat App - @@ -1479,7 +300,11 @@ -