diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -23,7 +23,8 @@ def read_db(): with open(DB_FILE, 'r') as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError): - return {"users": {}, "chatrooms": {}, "messages": {}} + init_db() + return read_db() def write_db(data): with open(DB_FILE, 'w') as f: @@ -39,6 +40,7 @@ def index(): Virton Messenger + @@ -58,8 +60,8 @@ def index(): --success-color: #28a745; --error-color: #dc3545; --font-family: 'Inter', sans-serif; - --ton-purple: #6A5EE2; - --ton-purple-light: #948AE4; + --ton-color: #007EE5; + --ton-color-light: #0098EE; } * { @@ -82,6 +84,8 @@ def index(): width: 100vw; display: flex; flex-direction: column; + align-items: center; + justify-content: center; } .main-container { @@ -90,12 +94,17 @@ def index(): display: flex; flex-direction: column; transition: opacity 0.3s ease; + background-color: var(--bg-primary); } #login-view { + display: flex; + flex-direction: column; align-items: center; justify-content: center; text-align: center; + width: 100%; + height: 100%; background: radial-gradient(circle, #1a2a3a 0%, var(--bg-primary) 70%); } #login-view img { @@ -119,50 +128,80 @@ def index(): } #app-view { - display: none; - flex-direction: column; + display: none; /* Managed by JS */ + width: 100%; height: 100%; - overflow: hidden; + flex-direction: column; } - - .content-area { + + #content-area { flex-grow: 1; overflow: hidden; - position: relative; - padding-bottom: 60px; /* Height of nav bar */ + position: relative; /* For absolute positioning of view panels if needed */ } - .view { + .view-panel { width: 100%; height: 100%; position: absolute; top: 0; left: 0; - display: none; + display: none; /* Managed by JS */ flex-direction: column; background-color: var(--bg-primary); - overflow-y: auto; - -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */ + animation: fadeIn 0.3s ease; } - .view.active { + .view-panel.active-view { display: flex; } - - /* Chats View Specific Styles */ - #chats-view { - display: flex; /* Default display */ - flex-direction: column; + + @keyframes fadeIn { + from { opacity: 0.8; } + to { opacity: 1; } } - #chatroom-list-view { - display: flex; - flex-direction: column; - height: 100%; - width: 100%; + .panel-header { + padding: 16px; background-color: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); + 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; + } + + #chat-window-container { + width: 100%; /* Mobile default */ + height: 100%; + display: none; /* Mobile default, shown by JS */ + flex-direction: column; + background-color: var(--bg-primary); + } + .list-header { padding: 16px; border-bottom: 1px solid var(--border-color); @@ -191,9 +230,8 @@ def index(): margin-bottom: 8px; word-break: break-all; } - #user-nickname-summary { margin-bottom: 0; } - .username-form { display: flex; gap: 8px; margin-top: 8px;} + .username-form { display: flex; gap: 8px; } .username-input { flex-grow: 1; background-color: var(--bg-primary); @@ -213,19 +251,18 @@ def index(): border-radius: 6px; cursor: pointer; font-weight: 500; - transition: transform 0.2s ease, box-shadow 0.2s ease; + transition: transform 0.1s ease, box-shadow 0.1s ease; display: flex; align-items: center; justify-content: center; gap: 8px; } - .action-btn:disabled { + .action-btn:active { + transform: scale(0.95); + } + .action-btn:disabled { opacity: 0.5; cursor: not-allowed; - } - .action-btn:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 4px 15px rgba(0, 136, 204, 0.3); } .action-btn.small { padding: 8px 12px; @@ -247,6 +284,18 @@ def index(): } .chatroom-item:hover { background-color: var(--bg-hover); } + .user-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; + } + .user-item:hover { background-color: var(--bg-hover); } + + .avatar { width: 40px; height: 40px; @@ -257,22 +306,13 @@ def index(): font-weight: 600; color: white; flex-shrink: 0; - overflow: hidden; + user-select: none; } - .avatar.message-avatar { - width: 36px; - height: 36px; - } - .avatar img { - width: 100%; - height: 100%; - object-fit: cover; - } - .chatroom-info { + .list-item-info { flex-grow: 1; overflow: hidden; } - .chatroom-name { + .list-item-name { font-weight: 500; white-space: nowrap; overflow: hidden; @@ -286,7 +326,7 @@ def index(): } #chat-window-view { - display: none; /* Hidden by default on mobile */ + display: none; /* Mobile default */ flex-direction: column; height: 100%; width: 100%; @@ -306,7 +346,11 @@ def index(): background: none; border: none; cursor: pointer; - display: block; /* Shown by default on mobile */ + display: block; /* Mobile default */ + padding: 0; + width: 24px; + height: 24px; + flex-shrink: 0; } .back-btn svg { width: 24px; @@ -316,7 +360,17 @@ 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; @@ -333,7 +387,10 @@ def index(): max-width: 80%; } .message .avatar { + width: 32px; + height: 32px; align-self: flex-end; + font-size: 0.8rem; } .message-content { display: flex; @@ -348,7 +405,7 @@ def index(): cursor: pointer; } .message-bubble { - padding: 10px 14px; + padding: 8px 12px; border-radius: 18px; line-height: 1.4; word-wrap: break-word; @@ -382,7 +439,7 @@ def index(): .message-form { display: flex; - padding: 16px; + padding: 12px 16px; gap: 12px; background-color: var(--bg-secondary); border-top: 1px solid var(--border-color); @@ -402,77 +459,80 @@ def index(): #message-input:focus { border-color: var(--accent-blue); } .send-btn { - width: 44px; - height: 44px; + width: 40px; + height: 40px; border-radius: 50%; flex-shrink: 0; padding: 0; } - .send-btn svg { width: 20px; height: 20px; fill: white; } + .send-btn svg { width: 18px; height: 18px; fill: white; } - /* Users View Specific Styles */ - #users-view .view-header { - padding: 16px; - border-bottom: 1px solid var(--border-color); - flex-shrink: 0; - } - #users-view .view-header h2 { - font-size: 1.5rem; - font-weight: 600; + #users-list-container { + flex-grow: 1; + overflow-y: auto; } - #user-list { - flex-grow: 1; - overflow-y: auto; - padding: 0 16px; - } - .user-item { + + #my-profile-view .profile-details { + padding: 20px; display: flex; + flex-direction: column; align-items: center; - gap: 12px; - padding: 12px 0; - cursor: pointer; - border-bottom: 1px solid var(--border-color); - transition: background-color 0.2s ease; + 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); } - .user-item:last-child { border-bottom: none; } - .user-item:hover { background-color: var(--bg-hover); } - .user-item-info { - flex-grow: 1; - overflow: hidden; - } - .user-item-name { - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + #my-profile-view #profile-balance { + color: var(--ton-color-light); + font-weight: 500; } - .user-item-address { - font-size: 0.9rem; - color: var(--text-secondary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - /* Browser View Specific Styles */ - #browser-view .view-header { - padding: 16px; - border-bottom: 1px solid var(--border-color); - flex-shrink: 0; - } - #browser-view .view-header h2 { - font-size: 1.5rem; - font-weight: 600; - } - .browser-bar { - display: flex; - gap: 8px; - padding: 12px 16px; - border-bottom: 1px solid var(--border-color); - background-color: var(--bg-tertiary); - flex-shrink: 0; + #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; + } + #browser-address-bar { + display: flex; + padding: 8px 16px; + background-color: var(--bg-tertiary); + gap: 8px; } - .browser-url-input { + #browser-address-bar input { flex-grow: 1; padding: 8px 12px; border: 1px solid var(--border-color); @@ -480,134 +540,72 @@ def index(): color: var(--text-primary); border-radius: 6px; font-size: 0.9rem; - } - .browser-url-input:focus { outline: none; border-color: var(--accent-blue); } - .browser-iframe { - width: 100%; - flex-grow: 1; - border: none; - } - - /* Profile View Specific Styles */ - #profile-view { - padding: 24px; - align-items: center; - text-align: center; - overflow-y: auto; - } - #profile-view .avatar { - width: 80px; - height: 80px; - margin-bottom: 20px; - } - #profile-view h2 { - font-size: 1.8rem; - font-weight: 600; - margin-bottom: 8px; - } - #profile-view p { - font-size: 1rem; - color: var(--text-secondary); - margin-bottom: 8px; - } - #profile-view .action-btn { - margin-top: 20px; - width: auto; - padding: 12px 24px; - } - #profile-view #profile-qr-code { - background: white; - padding: 10px; - margin: 20px auto; - width: fit-content; - border-radius: 8px; - } - #profile-view .qr-label { - text-align: center; - color: var(--text-secondary); - font-size: 0.8rem; - margin-top: -10px; - margin-bottom: 20px; + outline: none; } - #profile-view .profile-balance { - font-size: 1.1rem; - font-weight: 500; - margin-top: 16px; - color: var(--accent-blue-light); + #browser-address-bar button { + padding: 8px 12px; + background: var(--accent-blue); + color: white; + border: none; + border-radius: 6px; + cursor: pointer; } - /* Bottom Navigation Bar */ #bottom-nav { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - height: 60px; - background-color: var(--bg-secondary); - border-top: 1px solid var(--border-color); display: flex; justify-content: space-around; align-items: center; - z-index: 500; - box-shadow: 0 -5px 15px rgba(0,0,0,0.2); + height: 60px; + background-color: var(--bg-secondary); + border-top: 1px solid var(--border-color); + flex-shrink: 0; } - .nav-item { - flex: 1; + flex-grow: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; - padding: 5px; cursor: pointer; color: var(--text-secondary); - transition: color 0.2s ease; font-size: 0.7rem; - text-align: center; - gap: 2px; + 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 { + .nav-item.active svg { fill: var(--accent-blue-light); } - .nav-item#nav-scan { - flex-grow: 0; - width: 56px; - height: 56px; - border-radius: 50%; - background: linear-gradient(45deg, var(--ton-purple), var(--ton-purple-light)); - color: white; - transform: translateY(-15px); - box-shadow: 0 5px 15px rgba(0,0,0,0.3); - transition: transform 0.2s ease, box-shadow 0.2s ease; - } - .nav-item#nav-scan:hover { - transform: translateY(-17px); - box-shadow: 0 7px 20px rgba(0,0,0,0.4); + .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#nav-scan svg { + .nav-item#qr-scanner-nav svg { fill: white; - width: 28px; - height: 28px; - } - .nav-item#nav-scan span { - display: none; /* Hide text below central icon */ + margin: 0; } - /* Modals */ .modal-overlay { position: fixed; top: 0; @@ -650,14 +648,12 @@ def index(): border: none; cursor: pointer; font-weight: 500; - transition: background-color 0.2s ease; } .secondary-btn { background-color: var(--bg-hover); color: white; } - .secondary-btn:hover { background-color: #3a3d45; } #status-bar { position: fixed; - bottom: calc(60px + 20px); /* Above nav bar */ + bottom: 70px; /* Above nav bar */ left: 50%; transform: translateX(-50%); background-color: var(--bg-tertiary); @@ -670,16 +666,18 @@ 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 (min-width 768px) */ + /* Desktop Layout */ @media (min-width: 768px) { body { - align-items: center; - justify-content: center; + padding: 20px; + background-color: var(--bg-secondary); } .main-container { max-width: 1100px; @@ -688,81 +686,69 @@ def index(): overflow: hidden; box-shadow: 0 10px 40px rgba(0,0,0,0.3); border: 1px solid var(--border-color); - /* Remove fixed positioning for login view */ - position: relative; - bottom: auto; - left: auto; - transform: none; - padding-bottom: 0; /* No nav bar padding on desktop container */ + flex-direction: row; } - #app-view { - flex-direction: row; /* Side-by-side layout */ - } - .content-area { - flex-grow: 1; - padding-bottom: 0; /* No padding for desktop layout */ - position: static; /* Static positioning */ - overflow: hidden; /* Prevent content area scroll bar */ - display: flex; /* Use flex for side-by-side views if needed, or handle within views */ + #login-view { + border-radius: 12px; } - .view { - position: static; /* Static positioning in desktop flex layout */ - overflow-y: hidden; /* Prevent individual view scroll bars unless needed */ + #app-view { + flex-direction: row; } - #chats-view { - flex-direction: row; /* Side-by-side list and window */ + + #bottom-nav { + display: none; /* Hide bottom nav on desktop */ } - #chatroom-list-view { - width: 320px; - flex-shrink: 0; - border-right: 1px solid var(--border-color); - display: flex !important; /* Always show list on desktop */ - overflow-y: auto; /* Add scroll to list view */ - height: 100%; - } - #chat-window-view { - width: auto; - flex-grow: 1; - display: flex !important; /* Always show window on desktop */ - overflow: hidden; /* Handle message scroll within messages-container */ - height: 100%; + #content-area { + flex-direction: row; /* Layout views side-by-side or within a split */ + position: static; /* No absolute positioning */ } - .back-btn { display: none !important; } /* Hide back button on desktop */ + .view-panel { + position: static; /* No absolute positioning */ + width: 100%; /* Takes full content width by default */ + } - /* Ensure other views take full space when active */ - #users-view.active, #browser-view.active, #profile-view.active { - width: 100%; - height: 100%; - overflow-y: auto; /* Add scroll back for these views */ + #chatrooms-view.active-view { + display: flex; /* Ensure flex for split */ + flex-direction: row; /* Arrange list and window side by side */ } - #users-view, #browser-view, #profile-view { - /* When inactive, they are hidden by JS, no need for specific desktop hidden style */ + + #chatroom-list-container { + width: 320px; /* Fixed width for list */ + flex-shrink: 0; + border-right: 1px solid var(--border-color); + display: flex; /* Always visible */ } + #chat-window-container { + width: auto; /* Take remaining space */ + flex-grow: 1; + display: flex; /* Always visible */ + } - /* Hide bottom nav bar on desktop */ - #bottom-nav { - display: none; - } + .back-btn { + display: none !important; /* Hide back button on desktop */ + } - #status-bar { - bottom: 20px; /* Revert status bar position */ + .chat-header #chat-header-title { + text-align: left; + } + .chat-header { + justify-content: flex-start; } - #profile-view { - padding-top: 40px; /* Adjust padding */ + #users-view.active-view, + #browser-view.active-view, + #my-profile-view.active-view { + display: flex; /* These views take the full content area */ } - #profile-view .avatar { - width: 100px; - height: 100px; - margin-bottom: 24px; + + #status-bar { + bottom: 20px; /* Move back to bottom */ } - #profile-view h2 { font-size: 2rem; } - #profile-view p { font-size: 1.1rem; } } @@ -776,11 +762,10 @@ def index():
-
- - -
-
+
+ +
+

Чаты

@@ -794,16 +779,14 @@ def index():
-
+
+ +
-
+
TON Symbol

Выберите чат

@@ -828,72 +811,63 @@ def index():
- -
-
-

Пользователи

+
+
Пользователи
+
+
-
- -
-
-

Браузер

-
-
- - +
+
Браузер
+ + + - +
- -
-

Мой профиль

-
-

-

-

- -
-

Отсканируйте для открытия профиля

- - - - +
+
Мой профиль
+
+
+

+

+

+
+ + +
+
+

Отсканируйте для быстрого добавления

+
- -
- - +
+ + + +
- -