diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -22,9 +22,15 @@ def read_db(): try: with open(DB_FILE, 'r') as f: return json.load(f) - except (FileNotFoundError, json.JSONDecodeError): + except FileNotFoundError: init_db() return read_db() + except json.JSONDecodeError: + return { + "users": {}, + "chatrooms": {}, + "messages": {} + } def write_db(data): with open(DB_FILE, 'w') as f: @@ -40,7 +46,6 @@ def index(): Virton Messenger - @@ -60,8 +65,7 @@ def index(): --success-color: #28a745; --error-color: #dc3545; --font-family: 'Inter', sans-serif; - --ton-color: #007EE5; - --ton-color-light: #0098EE; + --navbar-height: 60px; } * { @@ -83,7 +87,6 @@ def index(): height: 100vh; width: 100vw; display: flex; - flex-direction: column; align-items: center; justify-content: center; } @@ -94,7 +97,6 @@ def index(): display: flex; flex-direction: column; transition: opacity 0.3s ease; - background-color: var(--bg-primary); } #login-view { @@ -128,78 +130,38 @@ def index(): } #app-view { - display: none; /* Managed by JS */ + display: none; width: 100%; height: 100%; flex-direction: column; } - - #content-area { + + .main-content-area { flex-grow: 1; overflow: hidden; - position: relative; /* For absolute positioning of view panels if needed */ - } - - .view-panel { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - display: none; /* Managed by JS */ - flex-direction: column; - background-color: var(--bg-primary); - animation: fadeIn 0.3s ease; - } - - .view-panel.active-view { display: flex; + flex-direction: row; /* Default desktop layout */ + height: calc(100% - var(--navbar-height)); } - @keyframes fadeIn { - from { opacity: 0.8; } - to { opacity: 1; } - } - - .panel-header { - padding: 16px; - background-color: var(--bg-secondary); - border-bottom: 1px solid var(--border-color); + #chatroom-list-view, + #users-list-view { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; /* Mobile default */ flex-shrink: 0; - font-size: 1.2rem; - font-weight: 600; - text-align: center; - } - - #chatrooms-view .panel-header, - #users-view .panel-header, - #my-profile-view .panel-header, - #browser-view .panel-header { - display: flex; - align-items: center; - justify-content: center; - } - - - #chatrooms-view { - /* Special layout for chat list + chat window on desktop */ - } - - #chatroom-list-container { - width: 100%; /* Mobile default */ - height: 100%; - display: flex; /* Mobile default */ - flex-direction: column; - background-color: var(--bg-secondary); - overflow-y: auto; + background-color: var(--bg-secondary); } - - #chat-window-container { - width: 100%; /* Mobile default */ - height: 100%; - display: none; /* Mobile default, shown by JS */ - flex-direction: column; - background-color: var(--bg-primary); + + #chat-window-view, + #browser-view { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; /* Mobile default */ + flex-grow: 1; + background-color: var(--bg-primary); } .list-header { @@ -223,12 +185,12 @@ def index(): background-color: var(--bg-tertiary); border-radius: 8px; margin-bottom: 16px; + word-break: break-all; } - #user-wallet-summary, #user-nickname-summary { + #user-wallet, #user-nickname { font-size: 0.9rem; color: var(--text-secondary); margin-bottom: 8px; - word-break: break-all; } .username-form { display: flex; gap: 8px; } @@ -251,39 +213,27 @@ def index(): border-radius: 6px; cursor: pointer; font-weight: 500; - transition: transform 0.1s ease, box-shadow 0.1s ease; + transition: transform 0.2s ease, box-shadow 0.2s ease; display: flex; align-items: center; justify-content: center; gap: 8px; } - .action-btn:active { - transform: scale(0.95); - } - .action-btn:disabled { - opacity: 0.5; - cursor: not-allowed; + .action-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(0, 136, 204, 0.3); } .action-btn.small { padding: 8px 12px; font-size: 0.9rem; } - #chatroom-list { + #chatroom-list, + #users-list { flex-grow: 1; overflow-y: auto; } - .chatroom-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 16px; - cursor: pointer; - border-bottom: 1px solid var(--border-color); - transition: background-color 0.2s ease; - } - .chatroom-item:hover { background-color: var(--bg-hover); } - + .chatroom-item, .user-item { display: flex; align-items: center; @@ -293,9 +243,9 @@ def index(): border-bottom: 1px solid var(--border-color); transition: background-color 0.2s ease; } + .chatroom-item:hover, .user-item:hover { background-color: var(--bg-hover); } - .avatar { width: 40px; height: 40px; @@ -306,18 +256,27 @@ def index(): font-weight: 600; color: white; flex-shrink: 0; - user-select: none; + font-size: 1.1rem; } - .list-item-info { + .chatroom-info, + .user-info { flex-grow: 1; overflow: hidden; } - .list-item-name { + .chatroom-name, + .user-nickname { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + .user-address { + font-size: 0.8rem; + color: var(--text-secondary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } .lock-icon { width: 16px; height: 16px; @@ -325,14 +284,6 @@ def index(): flex-shrink: 0; } - #chat-window-view { - display: none; /* Mobile default */ - flex-direction: column; - height: 100%; - width: 100%; - background-color: var(--bg-primary); - } - .chat-header { display: flex; align-items: center; @@ -346,11 +297,7 @@ def index(): background: none; border: none; cursor: pointer; - display: block; /* Mobile default */ - padding: 0; - width: 24px; - height: 24px; - flex-shrink: 0; + display: block; /* Show on mobile by default */ } .back-btn svg { width: 24px; @@ -360,17 +307,7 @@ def index(): #chat-header-title { font-size: 1.2rem; font-weight: 600; - flex-grow: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; } - #chat-header-avatar { - width: 36px; - height: 36px; - font-size: 0.9rem; - } - #messages-container { flex-grow: 1; @@ -387,10 +324,10 @@ def index(): max-width: 80%; } .message .avatar { - width: 32px; - height: 32px; + width: 36px; + height: 36px; align-self: flex-end; - font-size: 0.8rem; + font-size: 1rem; } .message-content { display: flex; @@ -405,7 +342,7 @@ def index(): cursor: pointer; } .message-bubble { - padding: 8px 12px; + padding: 10px 14px; border-radius: 18px; line-height: 1.4; word-wrap: break-word; @@ -439,7 +376,7 @@ def index(): .message-form { display: flex; - padding: 12px 16px; + padding: 16px; gap: 12px; background-color: var(--bg-secondary); border-top: 1px solid var(--border-color); @@ -459,153 +396,41 @@ def index(): #message-input:focus { border-color: var(--accent-blue); } .send-btn { - width: 40px; - height: 40px; + width: 44px; + height: 44px; border-radius: 50%; flex-shrink: 0; padding: 0; } - .send-btn svg { width: 18px; height: 18px; fill: white; } + .send-btn svg { width: 20px; height: 20px; fill: white; } - #users-list-container { - flex-grow: 1; - overflow-y: auto; - } - - #my-profile-view .profile-details { - padding: 20px; + #browser-view .browser-url-bar { display: flex; - flex-direction: column; - align-items: center; - gap: 16px; - } - #my-profile-view .profile-details .avatar { - width: 80px; - height: 80px; - font-size: 2rem; - margin-bottom: 10px; - } - #my-profile-view #profile-username, - #my-profile-view #profile-address, - #my-profile-view #profile-balance { - width: 100%; - text-align: center; - word-break: break-all; - } - #my-profile-view #profile-username { - font-size: 1.5rem; - font-weight: 600; - } - #my-profile-view #profile-address, - #my-profile-view #profile-balance { - font-size: 1rem; - color: var(--text-secondary); - } - #my-profile-view #profile-balance { - color: var(--ton-color-light); - font-weight: 500; - } - - #my-profile-view #profile-qr-code { - background: white; - padding: 10px; - margin-top: 20px; - width: fit-content; - border-radius: 8px; - box-shadow: 0 2px 8px rgba(0,0,0,0.1); - } - #my-profile-view .username-form { - width: 100%; - max-width: 300px; - margin-top: 20px; - } - - - #browser-view iframe { - width: 100%; - flex-grow: 1; - border: none; + padding: 12px 16px; + gap: 8px; + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; } - #browser-address-bar { - display: flex; - padding: 8px 16px; - background-color: var(--bg-tertiary); - gap: 8px; - } - #browser-address-bar input { + #browser-view .browser-url-input { flex-grow: 1; padding: 8px 12px; border: 1px solid var(--border-color); - background-color: var(--bg-primary); + background-color: var(--bg-tertiary); color: var(--text-primary); border-radius: 6px; - font-size: 0.9rem; outline: none; + font-size: 0.9rem; } - #browser-address-bar button { - padding: 8px 12px; - background: var(--accent-blue); - color: white; - border: none; - border-radius: 6px; - cursor: pointer; - } - + #browser-view .browser-url-input:focus { border-color: var(--accent-blue); } - #bottom-nav { - display: flex; - justify-content: space-around; - align-items: center; - height: 60px; - background-color: var(--bg-secondary); - border-top: 1px solid var(--border-color); - flex-shrink: 0; - } - .nav-item { + #browser-view iframe { flex-grow: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - cursor: pointer; - color: var(--text-secondary); - font-size: 0.7rem; - transition: color 0.2s ease; - user-select: none; - padding: 4px 0; - } - .nav-item svg { - width: 24px; - height: 24px; - fill: var(--text-secondary); - margin-bottom: 4px; - transition: fill 0.2s ease; - } - .nav-item.active { - color: var(--accent-blue-light); - } - .nav-item.active svg { - fill: var(--accent-blue-light); + width: 100%; + height: 100%; + border: none; } - .nav-item#qr-scanner-nav { - position: relative; - top: -15px; - width: 50px; - height: 50px; - border-radius: 50%; - background: linear-gradient(45deg, var(--accent-blue), var(--accent-blue-light)); - color: white; - box-shadow: 0 4px 10px rgba(0, 136, 204, 0.4); - flex-grow: 0; - margin: 0 10px; - } - .nav-item#qr-scanner-nav svg { - fill: white; - margin: 0; - } - - .modal-overlay { position: fixed; top: 0; @@ -631,7 +456,7 @@ def index(): } .modal-content h3 { margin-bottom: 20px; font-weight: 600; font-size: 1.3rem; } .modal-content label { display: block; margin-bottom: 8px; font-size: 0.9rem; color: var(--text-secondary); } - .modal-content input { + .modal-content input:not([type="checkbox"]) { width: 100%; padding: 12px; margin-bottom: 16px; @@ -642,18 +467,38 @@ def index(): font-size: 1rem; } .modal-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 8px; } + .modal-actions.column { flex-direction: column; align-items: stretch; } .modal-btn { padding: 10px 20px; border-radius: 6px; border: none; cursor: pointer; font-weight: 500; + text-align: center; } .secondary-btn { background-color: var(--bg-hover); color: white; } + #profile-modal .modal-content { text-align: center; } + #profile-avatar-container { margin: 20px auto; display: inline-block; } + #profile-username { font-size: 1.2rem; font-weight: 600; } + #profile-address { color: var(--text-secondary); font-size: 0.9rem; word-break: break-all; margin-top: 8px; } + #profile-qr-code { background: white; padding: 10px; margin: 20px auto; width: fit-content; border-radius: 8px; } + #profile-modal .caption { text-align: center; color: var(--text-secondary); font-size: 0.8rem; margin-top: -10px; margin-bottom: 20px; } + #profile-balance { margin-top: 16px; font-size: 1rem; color: var(--text-secondary); } + + + #scanner-modal .modal-content { text-align: center; } + #qr-reader { + width: 100%; + border: 1px solid var(--border-color); + margin-top: 16px; + border-radius: 8px; + overflow: hidden; + } + #status-bar { position: fixed; - bottom: 70px; /* Above nav bar */ + bottom: calc(var(--navbar-height) + 20px); /* Position above navbar */ left: 50%; transform: translateX(-50%); background-color: var(--bg-tertiary); @@ -666,19 +511,77 @@ def index(): transition: opacity 0.3s, visibility 0.3s; z-index: 2000; box-shadow: 0 5px 15px rgba(0,0,0,0.3); - max-width: 90%; - word-break: break-word; } #status-bar.success { background-color: var(--success-color); } #status-bar.error { background-color: var(--error-color); } #status-bar.visible { opacity: 1; visibility: visible; } - /* Desktop Layout */ + .navbar { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + height: var(--navbar-height); + background-color: var(--bg-secondary); + border-top: 1px solid var(--border-color); + display: flex; + justify-content: space-around; + align-items: center; + z-index: 900; + } + .navbar-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + flex-grow: 1; + height: 100%; + color: var(--text-secondary); + font-size: 0.75rem; + cursor: pointer; + transition: color 0.2s ease; + } + .navbar-item:hover { + color: var(--text-primary); + } + .navbar-item.active { + color: var(--accent-blue-light); + } + .navbar-item svg { + width: 24px; + height: 24px; + margin-bottom: 4px; + fill: currentColor; /* Use parent color */ + } + .navbar-item.scan-qr-item { + position: relative; + top: -15px; /* Lift button slightly */ + width: 50px; + height: 50px; + background: linear-gradient(45deg, var(--accent-blue), var(--accent-blue-light)); + border-radius: 50%; + box-shadow: 0 5px 15px rgba(0, 136, 204, 0.3); + color: white; + display: flex; + align-items: center; + justify-content: center; + font-size: 0; /* Hide text */ + flex-grow: 0; + } + .navbar-item.scan-qr-item svg { + margin-bottom: 0; + width: 28px; + height: 28px; + } + .navbar-item.scan-qr-item:hover { + color: white; /* Keep color white on hover */ + transform: translateY(-2px); + box-shadow: 0 7px 20px rgba(0, 136, 204, 0.4); + } + + + /* Desktop Styles */ @media (min-width: 768px) { - body { - padding: 20px; - background-color: var(--bg-secondary); - } .main-container { max-width: 1100px; max-height: 800px; @@ -686,68 +589,50 @@ def index(): overflow: hidden; box-shadow: 0 10px 40px rgba(0,0,0,0.3); border: 1px solid var(--border-color); - flex-direction: row; - } - - #login-view { - border-radius: 12px; } #app-view { - flex-direction: row; + flex-direction: column; /* Keep column for desktop */ } - #bottom-nav { - display: none; /* Hide bottom nav on desktop */ - } - - #content-area { - flex-direction: row; /* Layout views side-by-side or within a split */ - position: static; /* No absolute positioning */ + .main-content-area { + flex-direction: row; /* Desktop layout */ + height: 100%; /* Desktop uses split view, not offset by navbar */ } - .view-panel { - position: static; /* No absolute positioning */ - width: 100%; /* Takes full content width by default */ - } - - #chatrooms-view.active-view { - display: flex; /* Ensure flex for split */ - flex-direction: row; /* Arrange list and window side by side */ - } - - #chatroom-list-container { - width: 320px; /* Fixed width for list */ + #chatroom-list-view, + #users-list-view { + width: 320px; flex-shrink: 0; border-right: 1px solid var(--border-color); - display: flex; /* Always visible */ + display: flex !important; /* Always show list on desktop */ } - #chat-window-container { - width: auto; /* Take remaining space */ - flex-grow: 1; - display: flex; /* Always visible */ - } + #chat-window-view { + width: auto; + flex-grow: 1; + display: flex !important; /* Always show chat on desktop */ + } - .back-btn { - display: none !important; /* Hide back button on desktop */ - } + #browser-view { + width: auto; + flex-grow: 1; + display: flex !important; /* Always show browser when active */ + } - .chat-header #chat-header-title { - text-align: left; - } - .chat-header { - justify-content: flex-start; - } + .back-btn { display: none !important; } /* Hide back button on desktop */ - #users-view.active-view, - #browser-view.active-view, - #my-profile-view.active-view { - display: flex; /* These views take the full content area */ - } + .navbar { + position: static; /* Navbar is integrated into layout or hidden on desktop */ + height: 0; /* Make navbar height 0 to not take space */ + border-top: none; + } + .navbar-item { + display: none; /* Hide navbar items on desktop */ + } #status-bar { - bottom: 20px; /* Move back to bottom */ + bottom: 20px; /* Move status bar down on desktop */ } } @@ -762,110 +647,100 @@ def index():
-
- -
-
-
-
-

Чаты

-
- -
-
- -
-
- -
-
- -
-
- TON Symbol -

Выберите чат

-

Начните общение в одном из существующих чатов или создайте свой собственный.

-
- +
+
-
-
Пользователи
-
- -
-
- -
-
Браузер
-
- - -
- -
+ -
-
Мой профиль
-
-
-

-

-

-
- - +
+
+ TON Symbol +

Выберите чат

+

Начните общение в одном из существующих чатов или создайте свой собственный.

+
+ +
+ +
- +
+