CVNSS commited on
Commit
1fef416
·
verified ·
1 Parent(s): 300677f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +193 -77
index.html CHANGED
@@ -7,138 +7,254 @@
7
  <style>
8
  :root{
9
  --primary:#1a73e8; --bg:#f5f6f8; --text:#202124;
10
- /* Che kín header + ô Join tlk.io (không che ô gõ tin nhắn) */
11
- --ov-top:200px; /* nếu còn hở ô Join => tăng 220–260px */
12
- --ov-right:260px; /* cột phải 220–300px tùy màn hình */
13
  }
14
  *{ box-sizing:border-box }
15
- body{ margin:0; font-family:"Google Sans",Arial,sans-serif;
16
- background:var(--bg); color:var(--text); display:flex; flex-direction:column; min-height:100vh; }
17
- header{ background:var(--primary); color:#fff; padding:16px; text-align:center; font-size:20px; font-weight:600;
18
- box-shadow:0 2px 6px rgba(0,0,0,.1); }
19
- .card{ width:min(940px,92vw); margin:28px auto; background:#fff; border-radius:12px;
20
- box-shadow:0 6px 18px rgba(0,0,0,.08); padding:22px; }
21
- h2{ margin:0 0 14px 0; font-weight:600 }
22
- .row{ display:flex; gap:10px; flex-wrap:wrap }
23
- input[type="text"]{ flex:1 1 260px; padding:12px 14px; font-size:16px; border:1px solid #dadce0; border-radius:8px; }
 
 
 
 
 
 
 
 
 
 
 
24
  input[type="text"]:focus{ outline:none; border-color:var(--primary) }
25
- button{ padding:12px 18px; border:none; border-radius:8px; background:var(--primary); color:#fff; font-weight:600; cursor:pointer; }
26
- button:hover{ background:#0b5ed7 }
 
 
 
 
 
 
27
  .ghost{ background:#e9eef6; color:#174ea6 }
28
  .secondary{ background:#5f6368 }
29
  .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace }
 
30
  #chat-box{ display:none }
31
- .pill{ display:inline-block; background:#eef3fd; color:#174ea6; padding:6px 10px; border-radius:999px; font-size:14px; margin-bottom:10px; }
32
-
 
 
 
 
33
  .chat-wrap{ position:relative; border:1px solid #e3e6ea; border-radius:10px; overflow:hidden }
34
  iframe{ width:100%; height:72vh; min-height:520px; border:0; background:#fff }
35
-
36
- /* Overlays: che hẳn header + ô Join + cột phải + footer tlk.io */
37
- .ov-top{ position:absolute; left:0; right:0; top:0; height:var(--ov-top);
38
- background:#fff; z-index:3; pointer-events:none; box-shadow:0 8px 10px -10px rgba(0,0,0,.12); }
39
- .ov-right{ position:absolute; top:0; right:0; bottom:0; width:var(--ov-right);
40
- background:#fff; z-index:2; pointer-events:none; box-shadow:-8px 0 10px -10px rgba(0,0,0,.12); }
41
- .ov-bottom{ position:absolute; left:0; right:0; bottom:0; height:100px;
42
- background:#fff; z-index:2; pointer-events:none; box-shadow:0 -8px 10px -10px rgba(0,0,0,.12); }
43
-
 
 
 
44
  .links{ display:none; gap:8px; align-items:center; flex-wrap:wrap; margin-top:12px }
45
  .link-badge{ background:#f1f3f4; padding:6px 8px; border-radius:6px }
46
- .toast{ position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
47
- background:#323232; color:#fff; padding:10px 14px; border-radius:8px; font-size:14px; opacity:0;
48
- pointer-events:none; transition:opacity .2s ease; }
 
 
49
  .toast.show{ opacity:1 }
50
  footer{ margin-top:auto; text-align:center; color:#6c727a; font-size:13px; padding:16px }
51
- @media (max-width:640px){ :root{ --ov-right:200px } }
 
 
52
  </style>
53
  </head>
54
  <body>
55
  <header>💬 Chat CVNSS4.0</header>
56
 
57
- <!-- tạo phòng & vào chat -->
58
  <section id="login" class="card">
59
  <h2>Tham gia phòng chat</h2>
60
- <div class="row" style="margin-bottom:10px;">
61
- <input type="text" id="nickname" placeholder="Nhập tên của bạn…">
62
- <button id="joinBtn">Vào Chat</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  </div>
64
- <div class="row">
 
65
  <button class="ghost" id="newRoomBtn">✨ Tạo phòng bí mật</button>
 
66
  </div>
67
 
68
- <div id="linkArea" class="links">
69
  <span>🔗 Link phòng:</span>
70
  <span id="roomUrl" class="link-badge mono"></span>
71
- <button class="secondary" id="copyBtn">📋 Copy</button>
72
  </div>
73
  </section>
74
 
75
- <!-- khối chat -->
76
  <section id="chat-box" class="card">
77
  <span id="roomPill" class="pill"></span>
78
  <div class="chat-wrap">
79
  <div class="ov-top"></div>
80
  <div class="ov-right"></div>
81
- <div class="ov-bottom"></div>
82
  <iframe id="chatFrame" title="tlk.io chat"></iframe>
83
  </div>
84
  </section>
85
 
86
- <div id="toast" class="toast">Đã copy link phòng!</div>
87
 
88
  <footer>
89
  Nguồn: Sản phẩm thử nghiệm của Team CVNSS4.0 • Đóng tab là xóa hết dữ liệu ✅
90
  </footer>
91
 
92
  <script>
93
- // --- trạng thái & URL ---
94
- const qs = new URLSearchParams(location.search);
95
- let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
96
- const base = `${location.origin}${location.pathname}`;
97
- document.getElementById("roomPill").textContent = "Phòng: " + room;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  // Toast helper
100
- const toastEl = document.getElementById('toast');
101
- function toast(msg){ toastEl.textContent = msg; toastEl.classList.add('show'); setTimeout(()=>toastEl.classList.remove('show'), 1400); }
102
-
103
- // --- Vào chat: luôn ẩn Join gốc bằng overlay, chỉ dùng form ngoài ---
104
- document.getElementById("joinBtn").onclick = () => {
105
- const name = (document.getElementById("nickname").value || "").trim() || "Guest";
106
- document.getElementById("login").style.display = "none";
107
- document.getElementById("chat-box").style.display = "block";
108
- const url = `https://tlk.io/${encodeURIComponent(room)}?nickname=${encodeURIComponent(name)}`;
109
- document.getElementById("chatFrame").src = url;
110
- };
 
 
 
 
 
 
 
 
 
 
111
 
112
- // --- Tạo phòng mật: random id + cập nhật URL + hiện link + copy & ẩn ngay ---
113
- document.getElementById("newRoomBtn").onclick = () => {
114
- const rnd = Math.random().toString(36).slice(2,8);
115
- room = `cvnss4-0-${rnd}`;
116
- const link = `${base}?room=${room}`;
117
 
118
- // cập nhật pill & URL hiện tại để share đúng phòng
119
- document.getElementById("roomPill").textContent = "Phòng: " + room;
 
 
 
 
 
 
 
 
 
 
 
120
  history.replaceState(null, "", `?room=${room}`);
121
 
122
- // hiện block link
123
- const area = document.getElementById("linkArea");
124
- document.getElementById("roomUrl").textContent = link;
125
- area.style.display = "flex";
126
 
127
- // copy & ẨN NGAY block cho gọn, vẫn hiện toast báo
128
- const copyBtn = document.getElementById("copyBtn");
129
- copyBtn.onclick = async () => {
130
- try {
131
- if (navigator.clipboard && navigator.clipboard.writeText) {
 
 
 
 
 
 
 
132
  await navigator.clipboard.writeText(link);
 
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
- // nếu có Web Share API, ưu tiên dùng (không bắt buộc)
135
- if (navigator.share) { try { await navigator.share({ title:"Phòng chat CVNSS4.0", url:link }); } catch(e){} }
136
  toast("✅ Đã copy link phòng!");
137
- } catch(e){ toast("⚠️ Sao chép không thành công—hãy copy thủ công"); }
138
- // Ẩn ngay khối link
139
- area.style.display = "none";
 
 
140
  };
141
- };
 
 
 
 
 
 
 
 
142
  </script>
143
  </body>
144
  </html>
 
7
  <style>
8
  :root{
9
  --primary:#1a73e8; --bg:#f5f6f8; --text:#202124;
10
+ /* Che kín header + ô Join tlk.io (KHÔNG che ô gõ tin nhắn ở đáy) */
11
+ --ov-top: clamp(180px, 24vh, 280px); /* nếu còn hở ô Join => tăng giá trị này */
12
+ --ov-right: 260px; /* cột phải thường ~240–300px */
13
  }
14
  *{ box-sizing:border-box }
15
+ body{
16
+ margin:0; font-family: "Google Sans", Arial, sans-serif;
17
+ background:var(--bg); color:var(--text);
18
+ display:flex; flex-direction:column; min-height:100vh;
19
+ }
20
+ header{
21
+ background:var(--primary); color:#fff; padding:16px; text-align:center;
22
+ font-size:20px; font-weight:600; box-shadow:0 2px 6px rgba(0,0,0,.1);
23
+ }
24
+ .card{
25
+ width:min(960px,92vw); margin:24px auto; background:#fff; border-radius:12px;
26
+ box-shadow:0 6px 18px rgba(0,0,0,.08); padding:22px;
27
+ }
28
+ h2{ margin:0 0 10px 0; font-weight:700 }
29
+ .subtle{ color:#5f6368; font-size:14px; margin:6px 0 14px }
30
+ .row{ display:flex; gap:10px; flex-wrap:wrap; align-items:center }
31
+ input[type="text"]{
32
+ flex:1 1 260px; padding:12px 14px; font-size:16px;
33
+ border:1px solid #dadce0; border-radius:8px;
34
+ }
35
  input[type="text"]:focus{ outline:none; border-color:var(--primary) }
36
+ button{
37
+ padding:12px 18px; border:none; border-radius:8px;
38
+ background:var(--primary); color:#fff; font-weight:700; cursor:pointer;
39
+ transition: transform .06s ease, filter .12s ease;
40
+ }
41
+ button:hover{ filter:brightness(0.96) }
42
+ button:active{ transform: translateY(1px) }
43
+ .btn-red{ background:#d93025; color:#ffeb3b; } /* Vào Chat: nền đỏ, chữ vàng */
44
  .ghost{ background:#e9eef6; color:#174ea6 }
45
  .secondary{ background:#5f6368 }
46
  .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace }
47
+ .muted{ color:#6c727a }
48
  #chat-box{ display:none }
49
+ .pill{ display:inline-block; background:#eef3fd; color:#174ea6;
50
+ padding:6px 10px; border-radius:999px; font-size:14px; margin-bottom:10px; }
51
+ .tag-danger{
52
+ display:inline-block; background:#d93025; color:#ffeb3b; font-weight:800;
53
+ padding:4px 10px; border-radius:999px; font-size:12px; letter-spacing:.3px;
54
+ }
55
  .chat-wrap{ position:relative; border:1px solid #e3e6ea; border-radius:10px; overflow:hidden }
56
  iframe{ width:100%; height:72vh; min-height:520px; border:0; background:#fff }
57
+ /* Overlays: che hẳn header + ô Join + cột phải của tlk.io, KHÔNG che đáy */
58
+ .ov-top{
59
+ position:absolute; left:0; right:0; top:0; height:var(--ov-top);
60
+ background:#fff; z-index:3; pointer-events:none;
61
+ box-shadow:0 8px 10px -10px rgba(0,0,0,.12);
62
+ }
63
+ .ov-right{
64
+ position:absolute; top:0; right:0; bottom:0; width:var(--ov-right);
65
+ background:#fff; z-index:2; pointer-events:none;
66
+ box-shadow:-8px 0 10px -10px rgba(0,0,0,.12);
67
+ }
68
+ /* KHÔNG dùng overlay đáy để không che ô gõ tin nhắn */
69
  .links{ display:none; gap:8px; align-items:center; flex-wrap:wrap; margin-top:12px }
70
  .link-badge{ background:#f1f3f4; padding:6px 8px; border-radius:6px }
71
+ .toast{
72
+ position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
73
+ background:#323232; color:#fff; padding:10px 14px; border-radius:8px; font-size:14px;
74
+ opacity:0; pointer-events:none; transition:opacity .2s ease;
75
+ }
76
  .toast.show{ opacity:1 }
77
  footer{ margin-top:auto; text-align:center; color:#6c727a; font-size:13px; padding:16px }
78
+ ol.guide{ margin:0; padding-left:20px }
79
+ ol.guide li{ margin:6px 0 }
80
+ @media (max-width:800px){ :root{ --ov-right: 0px } } /* mobile tlk.io thường không có cột phải */
81
  </style>
82
  </head>
83
  <body>
84
  <header>💬 Chat CVNSS4.0</header>
85
 
86
+ <!-- Hướng dẫn + form ngoài: luôn dùng form này, không bao giờ dùng Join trong tlk.io -->
87
  <section id="login" class="card">
88
  <h2>Tham gia phòng chat</h2>
89
+ <p class="subtle">Luồng 3 bước siêu gọn: nhập tên → <span class="muted">Vào Chat</span> → (tuỳ chọn) tạo phòng bí mật để mời người khác.</p>
90
+
91
+ <ol class="guide">
92
+ <li><b>Nhập tên</b> của bạn ở ô dưới đây (có thể sửa lại sau).</li>
93
+ <li>Nhấn <b>Vào Chat</b> (nút đỏ). <span class="muted">Form Join gốc của tlk.io sẽ bị ẩn hoàn toàn.</span></li>
94
+ <li>
95
+ <b>✨ Tạo phòng bí mật</b> nếu cần mời người khác (ngẫu nhiên ID + Copy link tự ẩn).
96
+ <div style="margin-top:6px">
97
+ <span class="muted">Nếu bạn không cần “✨ Tạo phòng bí mật”, hãy <u>bỏ qua bước này</u>.</span>
98
+ </div>
99
+ <div style="margin-top:8px">
100
+ <span class="tag-danger">Vào Chat</span>
101
+ </div>
102
+ </li>
103
+ </ol>
104
+
105
+ <div class="row" style="margin-top:12px;">
106
+ <input type="text" id="nickname" placeholder="Nhập tên của bạn…" autocomplete="name" />
107
+ <button id="joinBtn" class="btn-red">Vào Chat</button>
108
  </div>
109
+
110
+ <div class="row" style="margin-top:10px;">
111
  <button class="ghost" id="newRoomBtn">✨ Tạo phòng bí mật</button>
112
+ <span class="muted" id="roomHint"></span>
113
  </div>
114
 
115
+ <div id="linkArea" class="links" aria-live="polite">
116
  <span>🔗 Link phòng:</span>
117
  <span id="roomUrl" class="link-badge mono"></span>
118
+ <button class="secondary" id="copyBtn" title="Copy link để gửi cho mọi người">📋 Copy</button>
119
  </div>
120
  </section>
121
 
122
+ <!-- Khối chat -->
123
  <section id="chat-box" class="card">
124
  <span id="roomPill" class="pill"></span>
125
  <div class="chat-wrap">
126
  <div class="ov-top"></div>
127
  <div class="ov-right"></div>
 
128
  <iframe id="chatFrame" title="tlk.io chat"></iframe>
129
  </div>
130
  </section>
131
 
132
+ <div id="toast" class="toast" role="status" aria-live="polite">Đã copy link phòng!</div>
133
 
134
  <footer>
135
  Nguồn: Sản phẩm thử nghiệm của Team CVNSS4.0 • Đóng tab là xóa hết dữ liệu ✅
136
  </footer>
137
 
138
  <script>
139
+ // ========== Trạng thái & URL ==========
140
+ const qs = new URLSearchParams(location.search);
141
+ let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
142
+ const base = `${location.origin}${location.pathname}`;
143
+ const els = {
144
+ pill: document.getElementById("roomPill"),
145
+ login: document.getElementById("login"),
146
+ chatBox: document.getElementById("chat-box"),
147
+ frame: document.getElementById("chatFrame"),
148
+ name: document.getElementById("nickname"),
149
+ join: document.getElementById("joinBtn"),
150
+ newRoom: document.getElementById("newRoomBtn"),
151
+ linkArea: document.getElementById("linkArea"),
152
+ roomUrl: document.getElementById("roomUrl"),
153
+ copy: document.getElementById("copyBtn"),
154
+ toast: document.getElementById("toast"),
155
+ hint: document.getElementById("roomHint"),
156
+ };
157
+
158
+ // Prefill tên gần đây
159
+ const lastName = localStorage.getItem("cvnss4_name") || "";
160
+ if (lastName) els.name.value = lastName;
161
+ els.name.focus({ preventScroll:true });
162
+
163
+ // Gắn label phòng hiện tại
164
+ function syncRoomUI(){
165
+ els.pill.textContent = "Phòng: " + room;
166
+ els.hint.textContent = "(đang ở phòng " + room + ")";
167
+ }
168
+ syncRoomUI();
169
 
170
  // Toast helper
171
+ function toast(msg){
172
+ els.toast.textContent = msg;
173
+ els.toast.classList.add('show');
174
+ setTimeout(()=> els.toast.classList.remove('show'), 1400);
175
+ }
176
+
177
+ // Build URL tlk.io (dựa vào nickname)
178
+ function buildTlkUrl(name){
179
+ // tlk.io hỗ trợ ?nickname= để auto-join, nhờ vậy không cần form Join gốc
180
+ const nick = encodeURIComponent(name || "Guest");
181
+ const r = encodeURIComponent(room);
182
+ return `https://tlk.io/${r}?nickname=${nick}`;
183
+ }
184
+
185
+ // ====== Vào chat: luôn ẩn Join gốc bằng overlay, chỉ dùng form ngoài ======
186
+ function enterChat(){
187
+ const name = (els.name.value || "").trim() || "Guest";
188
+ localStorage.setItem("cvnss4_name", name);
189
+ els.login.style.display = "none";
190
+ els.chatBox.style.display = "block";
191
+ els.frame.src = buildTlkUrl(name);
192
 
193
+ // Scroll xuống khối chat cho chắc (mobile)
194
+ setTimeout(()=> els.chatBox.scrollIntoView({ behavior:"smooth", block:"start" }), 50);
195
+ }
 
 
196
 
197
+ els.join.addEventListener("click", enterChat);
198
+ els.name.addEventListener("keydown", (e)=>{
199
+ if (e.key === "Enter") enterChat();
200
+ });
201
+
202
+ // ====== Tạo phòng bí mật: random id + cập nhật URL + hiện link + copy & ẩn ngay ======
203
+ els.newRoom.addEventListener("click", async ()=>{
204
+ const rnd = Math.random().toString(36).slice(2, 8);
205
+ room = `cvnss4-0-${rnd}`;
206
+ const link= `${base}?room=${room}`;
207
+
208
+ // Cập nhật UI & URL
209
+ syncRoomUI();
210
  history.replaceState(null, "", `?room=${room}`);
211
 
212
+ // Hiện block link
213
+ els.roomUrl.textContent = link;
214
+ els.linkArea.style.display = "flex";
 
215
 
216
+ // Auto copy ngay khi tạo (nếu quyền cho phép)
217
+ try{
218
+ if (navigator.clipboard?.writeText) {
219
+ await navigator.clipboard.writeText(link);
220
+ toast("✅ Link đã copy! Gửi cho mọi người ngay.");
221
+ }
222
+ }catch(_){ /* bỏ qua */ }
223
+
224
+ // Gắn handler Copy (nếu cần copy thủ công lại)
225
+ els.copy.onclick = async ()=>{
226
+ try{
227
+ if (navigator.clipboard?.writeText) {
228
  await navigator.clipboard.writeText(link);
229
+ } else {
230
+ // Fallback: chọn nội dung để người dùng Ctrl+C
231
+ const sel = window.getSelection();
232
+ const range = document.createRange();
233
+ range.selectNodeContents(els.roomUrl);
234
+ sel.removeAllRanges(); sel.addRange(range);
235
+ document.execCommand("copy");
236
+ sel.removeAllRanges();
237
+ }
238
+ // Web Share API (không bắt buộc)
239
+ if (navigator.share){
240
+ try{ await navigator.share({ title:"Phòng chat CVNSS4.0", url:link }); }catch(_){}
241
  }
 
 
242
  toast("✅ Đã copy link phòng!");
243
+ } catch(e){
244
+ toast("⚠️ Sao chép không thành công—hãy copy thủ công");
245
+ }
246
+ // Ẩn ngay khối link cho gọn
247
+ els.linkArea.style.display = "none";
248
  };
249
+
250
+ // Tự ẩn khối link sau 12 giây nếu quên bấm Copy
251
+ setTimeout(()=> {
252
+ if (els.linkArea.style.display !== "none") els.linkArea.style.display = "none";
253
+ }, 12000);
254
+ });
255
+
256
+ // Nếu mở trang bằng link phòng, giữ nguyên: khách nhập tên ở ngoài → Vào Chat
257
+ // Không làm gì thêm để bảo đảm chỉ dùng form ngoài.
258
  </script>
259
  </body>
260
  </html>