CVNSS commited on
Commit
69abab1
·
verified ·
1 Parent(s): baed586

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +59 -82
index.html CHANGED
@@ -10,92 +10,64 @@
10
  --bg:#f7f9fc; --card:#ffffff; --text:#1f2937; --muted:#6b7280;
11
  --primary:#1a73e8; --danger:#d93025; --accent:#ffeb3b;
12
 
13
- /* Mặt nạ (mask) để ẩn phần thừa của tlk.io */
14
- --header-mask: 260px; /* dải trắng che icon mây + thanh xanh tiêu đề */
15
- --mask-right: clamp(220px, 24vw, 300px); /* dải trắng che cột phải */
16
  }
17
 
18
  *{box-sizing:border-box}
19
- body{
20
- margin:0; font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;
21
- background:var(--bg); color:var(--text); display:flex; flex-direction:column; min-height:100vh;
22
- }
23
- header{
24
- padding:14px 16px; text-align:center; font-weight:700;
25
- background:#fff; border-bottom:1px solid #e5e7eb;
26
- }
27
-
28
- .card{
29
- width:min(980px,94vw); margin:22px auto; background:var(--card);
30
- border:1px solid #e5e7eb; border-radius:12px; box-shadow:0 6px 18px rgba(0,0,0,.06);
31
- padding:18px;
32
- }
33
- h2{margin:0 0 6px}
34
- .muted{color:var(--muted)}
35
- .row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}
36
-
37
- input[type=text]{
38
- flex:1 1 260px; padding:12px 14px; font-size:16px;
39
- border:1px solid #d1d5db; border-radius:10px;
40
- }
41
- input[type=text]:focus{outline:none; border-color:var(--primary); box-shadow:0 0 0 3px rgba(26,115,232,.15)}
42
-
43
- button{padding:12px 16px; border:0; border-radius:10px; font-weight:700; cursor:pointer}
44
- .btn-red{background:var(--danger); color:var(--accent)}
45
- .btn-ghost{background:#eef2ff; color:#1e3a8a}
46
- .btn-secondary{background:#374151; color:#fff}
47
  .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
48
 
49
- /* Trạng thái gọn: chỉ tên + phòng */
50
- .status{
51
- display:none; align-items:center; gap:10px;
52
- padding:10px 12px; border:1px dashed #d1d5db; border-radius:10px; margin-bottom:10px; background:#f9fafb;
53
- }
54
- .me-pill{
55
- display:inline-flex; align-items:center; gap:6px;
56
- background:#fff3cd; color:#7a5b00; border:1px solid #ffe8a1; padding:6px 12px; border-radius:999px; font-weight:800;
57
- }
58
- .room-pill{display:inline-block; background:#e8f0fe; color:#174ea6; padding:6px 10px; border-radius:999px}
59
 
60
- /* Khung chat */
61
- .chat-wrap{
62
- position:relative; border:1px solid #e5e7eb; border-radius:10px; overflow:hidden; background:#fff;
63
- }
64
- iframe#chatFrame{width:100%; height:72vh; min-height:640px; border:0; background:#fff}
65
 
66
- /* Mask TRẮNG – không cản bấm/nhập (pointer-events:none) */
67
  .mask-header{
68
- position:absolute; left:0; right:var(--mask-right); top:0; height:var(--header-mask);
69
- background:#fff; pointer-events:none; user-select:none; z-index:5;
70
  box-shadow:0 8px 10px -10px rgba(0,0,0,.12);
71
  }
72
  .mask-right{
73
- position:absolute; top:0; right:0; bottom:0; width:var(--mask-right);
74
- background:#fff; pointer-events:none; user-select:none; z-index:4;
75
  box-shadow:-8px 0 10px -10px rgba(0,0,0,.12);
76
  }
77
 
78
  /* Link phòng tự ẩn */
79
- .links{display:none; gap:8px; align-items:center; flex-wrap:wrap; margin-top:10px}
80
- .link-badge{background:#f3f4f6; border:1px solid #e5e7eb; color:#111827; padding:6px 8px; border-radius:8px}
81
 
82
  /* Fallback khi iframe bị chặn */
83
- .error-box{
84
- display:none; gap:10px; align-items:center; justify-content:space-between;
85
- padding:12px; border:1px solid #fecaca; background:#fef2f2; border-radius:10px; margin-top:10px;
86
- }
87
  .error-text{color:#991b1b}
88
 
89
- .toast{
90
- position:fixed; left:50%; bottom:22px; transform:translateX(-50%);
91
- background:#111827; color:#f9fafb; border:1px solid #374151;
92
- padding:10px 14px; border-radius:10px; font-size:14px; opacity:0; pointer-events:none; transition:opacity .2s;
93
- }
94
  .toast.show{opacity:1}
95
 
96
- footer{margin-top:auto; text-align:center; color:#6b7280; font-size:13px; padding:16px}
97
-
98
- @media (max-width:820px){ :root{ --mask-right:0px } } /* mobile thường không có panel phải */
99
  </style>
100
  </head>
101
  <body>
@@ -103,15 +75,18 @@
103
 
104
  <section id="login" class="card">
105
  <h2>Tham gia phòng chat</h2>
106
- <p class="muted">Nhập tên → <b>Vào Chat</b> (nút đỏ) → *(tuỳ chọn)* <b>✨ Tạo phòng bí mật</b> để mời người khác. Nếu không cần “✨ Tạo phòng bí mật”, hãy bỏ qua bước này.</p>
 
107
  <div class="row" style="margin-top:8px">
108
  <input id="nickname" type="text" placeholder="Nhập tên của bạn…" autocomplete="name">
109
  <button id="joinBtn" class="btn-red">Vào Chat</button>
110
  </div>
 
111
  <div class="row" style="margin-top:10px">
112
  <button id="newRoomBtn" class="btn-ghost">✨ Tạo phòng bí mật</button>
113
  <span id="roomHint" class="muted"></span>
114
  </div>
 
115
  <div id="linkArea" class="links" aria-live="polite">
116
  <span>🔗 Link phòng:</span>
117
  <span id="roomUrl" class="link-badge mono"></span>
@@ -126,14 +101,15 @@
126
  </div>
127
 
128
  <div class="chat-wrap">
129
- <!-- Mask trắng: che icon mây + thanh xanh + panel phải; KHÔNG cản click/nhập -->
130
  <div class="mask-header" aria-hidden="true"></div>
131
- <div class="mask-right" aria-hidden="true"></div>
132
 
133
  <iframe id="chatFrame" title="tlk.io chat" referrerpolicy="no-referrer"
134
  allow="clipboard-read; clipboard-write"></iframe>
135
  </div>
136
 
 
137
  <div id="errorBox" class="error-box">
138
  <span class="error-text">⚠️ Không tải được khung chat (trình duyệt/ISP chặn iframe).</span>
139
  <a id="openNew" class="btn-red" style="text-decoration:none;padding:10px 12px;border-radius:10px" target="_blank" rel="noopener">Mở cửa sổ chat</a>
@@ -145,17 +121,11 @@
145
 
146
  <script>
147
  (() => {
148
- // --- State ---
149
  const qs = new URLSearchParams(location.search);
150
  let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
151
  const base = `${location.origin}${location.pathname}`;
152
 
153
- // Cho phép tinh chỉnh nhanh qua URL nếu cần: &hdr=260 &maskr=260
154
- const hdr = parseInt(qs.get("hdr"),10);
155
- if(!isNaN(hdr)) document.documentElement.style.setProperty('--header-mask', hdr+'px');
156
- const maskr = parseInt(qs.get("maskr"),10);
157
- if(!isNaN(maskr)) document.documentElement.style.setProperty('--mask-right', maskr+'px');
158
-
159
  const $ = id => document.getElementById(id);
160
  const els = {
161
  login: $("login"), box: $("chatBox"), frame: $("chatFrame"),
@@ -165,41 +135,48 @@
165
  status: $("statusBar"), toast: $("toast"), err: $("errorBox"), openNew: $("openNew"),
166
  };
167
 
 
168
  const toast = m => { els.toast.textContent = m; els.toast.classList.add("show"); setTimeout(()=>els.toast.classList.remove("show"), 1400); };
169
  const getName = () => (els.name.value || localStorage.getItem("cvnss4_name") || "Guest").trim() || "Guest";
170
  const setName = n => { els.me.textContent = n; localStorage.setItem("cvnss4_name", n); };
171
  const syncRoomUI = () => { els.pill.textContent = room; els.hint.textContent = `(đang ở phòng ${room})`; };
172
  const tlkUrl = n => `https://tlk.io/${encodeURIComponent(room)}?nickname=${encodeURIComponent(n)}#embed`;
173
 
 
174
  function mountChat(){
175
  const name = getName(); setName(name); syncRoomUI();
176
  els.status.style.display = "flex";
 
177
  const url = tlkUrl(name);
178
- els.frame.src = url; els.openNew.href = url; els.err.style.display = "none";
 
 
179
 
180
- // Watchdog: nếu iframe không load trong 6s → hiện fallback
181
  const timer = setTimeout(()=>{ els.err.style.display = "flex"; }, 6000);
182
  els.frame.addEventListener("load", ()=> clearTimeout(timer), {once:true});
183
  }
184
 
185
  function enterChat(){
186
  els.login.style.display = "none";
187
- els.box.style.display = "block";
188
- mountChat();
189
  }
190
 
191
- // Events
192
  els.join.addEventListener("click", enterChat);
193
  els.name.addEventListener("keydown", e => { if(e.key === "Enter") enterChat(); });
194
 
195
- // Secret room + copy tự ẩn
196
  els.newRoom.addEventListener("click", async ()=>{
197
  room = `cvnss4-0-${Math.random().toString(36).slice(2,8)}`;
198
  syncRoomUI();
199
  history.replaceState(null,"",`?room=${room}`);
 
200
  const link = `${base}?room=${room}`;
201
  els.roomUrl.textContent = link;
202
  els.linkArea.style.display = "flex";
 
203
  try{ await navigator.clipboard?.writeText?.(link); toast("✅ Đã copy link phòng!"); }catch(_){}
204
  setTimeout(()=>{ if(els.linkArea.style.display!=="none") els.linkArea.style.display="none"; }, 9000);
205
 
@@ -213,7 +190,7 @@
213
  };
214
  });
215
 
216
- // Prefill + auto-enter nếu đã có tên
217
  const last = localStorage.getItem("cvnss4_name"); if(last) els.name.value = last;
218
  syncRoomUI(); els.name.focus({preventScroll:true});
219
  if (qs.get("room") && (last || els.name.value.trim() !== "")) enterChat();
 
10
  --bg:#f7f9fc; --card:#ffffff; --text:#1f2937; --muted:#6b7280;
11
  --primary:#1a73e8; --danger:#d93025; --accent:#ffeb3b;
12
 
13
+ /* Mask trắng để ẩn phần thừa bên trong tlk.io */
14
+ --header-mask: 260px; /* che icon mây + thanh xanh tiêu đề */
15
+ --mask-right: clamp(220px, 24vw, 300px); /* che cột phải (user list/branding) */
16
  }
17
 
18
  *{box-sizing:border-box}
19
+ body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;
20
+ background:var(--bg);color:var(--text);display:flex;flex-direction:column;min-height:100vh}
21
+ header{padding:14px 16px;text-align:center;font-weight:700;background:#fff;border-bottom:1px solid #e5e7eb}
22
+
23
+ .card{width:min(980px,94vw);margin:22px auto;background:var(--card);
24
+ border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 6px 18px rgba(0,0,0,.06);padding:18px}
25
+ h2{margin:0 0 6px}.muted{color:var(--muted)}
26
+ .row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
27
+
28
+ input[type=text]{flex:1 1 260px;padding:12px 14px;font-size:16px;border:1px solid #d1d5db;border-radius:10px}
29
+ input[type=text]:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(26,115,232,.15)}
30
+
31
+ button{padding:12px 16px;border:0;border-radius:10px;font-weight:700;cursor:pointer}
32
+ .btn-red{background:#d93025;color:#ffeb3b}
33
+ .btn-ghost{background:#eef2ff;color:#1e3a8a}
34
+ .btn-secondary{background:#374151;color:#fff}
 
 
 
 
 
 
 
 
 
 
 
 
35
  .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
36
 
37
+ /* Thanh trạng thái gọn: Tên + Phòng */
38
+ .status{display:none;align-items:center;gap:10px;padding:10px 12px;border:1px dashed #d1d5db;border-radius:10px;margin-bottom:10px;background:#f9fafb}
39
+ .me-pill{display:inline-flex;align-items:center;gap:6px;background:#fff3cd;color:#7a5b00;border:1px solid #ffe8a1;padding:6px 12px;border-radius:999px;font-weight:800}
40
+ .room-pill{display:inline-block;background:#e8f0fe;color:#174ea6;padding:6px 10px;border-radius:999px}
 
 
 
 
 
 
41
 
42
+ /* KHUNG CHAT: không overlay che toàn phần */
43
+ .chat-wrap{position:relative;border:1px solid #e5e7eb;border-radius:10px;overflow:hidden;background:#fff}
44
+ iframe#chatFrame{width:100%;height:72vh;min-height:640px;border:0;background:#fff}
 
 
45
 
46
+ /* MASK TRẮNG – KHÔNG chặn /nhấn */
47
  .mask-header{
48
+ position:absolute;left:0;right:var(--mask-right);top:0;height:var(--header-mask);
49
+ background:#fff;pointer-events:none;user-select:none;z-index:5;
50
  box-shadow:0 8px 10px -10px rgba(0,0,0,.12);
51
  }
52
  .mask-right{
53
+ position:absolute;top:0;right:0;bottom:0;width:var(--mask-right);
54
+ background:#fff;pointer-events:none;user-select:none;z-index:4;
55
  box-shadow:-8px 0 10px -10px rgba(0,0,0,.12);
56
  }
57
 
58
  /* Link phòng tự ẩn */
59
+ .links{display:none;gap:8px;align-items:center;flex-wrap:wrap;margin-top:10px}
60
+ .link-badge{background:#f3f4f6;border:1px solid #e5e7eb;color:#111827;padding:6px 8px;border-radius:8px}
61
 
62
  /* Fallback khi iframe bị chặn */
63
+ .error-box{display:none;gap:10px;align-items:center;justify-content:space-between;padding:12px;border:1px solid #fecaca;background:#fef2f2;border-radius:10px;margin-top:10px}
 
 
 
64
  .error-text{color:#991b1b}
65
 
66
+ .toast{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);background:#111827;color:#f9fafb;border:1px solid #374151;padding:10px 14px;border-radius:10px;font-size:14px;opacity:0;pointer-events:none;transition:opacity .2s}
 
 
 
 
67
  .toast.show{opacity:1}
68
 
69
+ footer{margin-top:auto;text-align:center;color:#6b7280;font-size:13px;padding:16px}
70
+ @media (max-width:820px){ :root{ --mask-right:0px } } /* mobile hầu như không có panel phải */
 
71
  </style>
72
  </head>
73
  <body>
 
75
 
76
  <section id="login" class="card">
77
  <h2>Tham gia phòng chat</h2>
78
+ <p class="muted">Nhập tên → <b>Vào Chat</b> (nút đỏ) → *(tuỳ chọn)* <b>✨ Tạo phòng bí mật</b>. Nếu không cần “✨ Tạo phòng bí mật”, hãy bỏ qua bước này.</p>
79
+
80
  <div class="row" style="margin-top:8px">
81
  <input id="nickname" type="text" placeholder="Nhập tên của bạn…" autocomplete="name">
82
  <button id="joinBtn" class="btn-red">Vào Chat</button>
83
  </div>
84
+
85
  <div class="row" style="margin-top:10px">
86
  <button id="newRoomBtn" class="btn-ghost">✨ Tạo phòng bí mật</button>
87
  <span id="roomHint" class="muted"></span>
88
  </div>
89
+
90
  <div id="linkArea" class="links" aria-live="polite">
91
  <span>🔗 Link phòng:</span>
92
  <span id="roomUrl" class="link-badge mono"></span>
 
101
  </div>
102
 
103
  <div class="chat-wrap">
104
+ <!-- Mask trắng: che icon mây + thanh xanh + cột phải; KHÔNG chặn /nhấn -->
105
  <div class="mask-header" aria-hidden="true"></div>
106
+ <div class="mask-right" aria-hidden="true"></div>
107
 
108
  <iframe id="chatFrame" title="tlk.io chat" referrerpolicy="no-referrer"
109
  allow="clipboard-read; clipboard-write"></iframe>
110
  </div>
111
 
112
+ <!-- Fallback khi iframe bị chặn -->
113
  <div id="errorBox" class="error-box">
114
  <span class="error-text">⚠️ Không tải được khung chat (trình duyệt/ISP chặn iframe).</span>
115
  <a id="openNew" class="btn-red" style="text-decoration:none;padding:10px 12px;border-radius:10px" target="_blank" rel="noopener">Mở cửa sổ chat</a>
 
121
 
122
  <script>
123
  (() => {
124
+ // --- Trạng thái ---
125
  const qs = new URLSearchParams(location.search);
126
  let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
127
  const base = `${location.origin}${location.pathname}`;
128
 
 
 
 
 
 
 
129
  const $ = id => document.getElementById(id);
130
  const els = {
131
  login: $("login"), box: $("chatBox"), frame: $("chatFrame"),
 
135
  status: $("statusBar"), toast: $("toast"), err: $("errorBox"), openNew: $("openNew"),
136
  };
137
 
138
+ // --- Helpers ---
139
  const toast = m => { els.toast.textContent = m; els.toast.classList.add("show"); setTimeout(()=>els.toast.classList.remove("show"), 1400); };
140
  const getName = () => (els.name.value || localStorage.getItem("cvnss4_name") || "Guest").trim() || "Guest";
141
  const setName = n => { els.me.textContent = n; localStorage.setItem("cvnss4_name", n); };
142
  const syncRoomUI = () => { els.pill.textContent = room; els.hint.textContent = `(đang ở phòng ${room})`; };
143
  const tlkUrl = n => `https://tlk.io/${encodeURIComponent(room)}?nickname=${encodeURIComponent(n)}#embed`;
144
 
145
+ // --- Nạp iframe + fallback ---
146
  function mountChat(){
147
  const name = getName(); setName(name); syncRoomUI();
148
  els.status.style.display = "flex";
149
+
150
  const url = tlkUrl(name);
151
+ els.frame.src = url; // khung chat
152
+ els.openNew.href = url; // fallback mở ngoài
153
+ els.err.style.display = "none";
154
 
155
+ // Nếu 6s không load được → hiện fallback
156
  const timer = setTimeout(()=>{ els.err.style.display = "flex"; }, 6000);
157
  els.frame.addEventListener("load", ()=> clearTimeout(timer), {once:true});
158
  }
159
 
160
  function enterChat(){
161
  els.login.style.display = "none";
162
+ els.box.style.display = "block";
163
+ mountChat(); // không scrollIntoView → tránh giật khi Enter
164
  }
165
 
166
+ // --- Sự kiện ---
167
  els.join.addEventListener("click", enterChat);
168
  els.name.addEventListener("keydown", e => { if(e.key === "Enter") enterChat(); });
169
 
170
+ // Tạo phòng bí mật + Copy tự ẩn
171
  els.newRoom.addEventListener("click", async ()=>{
172
  room = `cvnss4-0-${Math.random().toString(36).slice(2,8)}`;
173
  syncRoomUI();
174
  history.replaceState(null,"",`?room=${room}`);
175
+
176
  const link = `${base}?room=${room}`;
177
  els.roomUrl.textContent = link;
178
  els.linkArea.style.display = "flex";
179
+
180
  try{ await navigator.clipboard?.writeText?.(link); toast("✅ Đã copy link phòng!"); }catch(_){}
181
  setTimeout(()=>{ if(els.linkArea.style.display!=="none") els.linkArea.style.display="none"; }, 9000);
182
 
 
190
  };
191
  });
192
 
193
+ // Prefill + auto-join nếu đã có tên
194
  const last = localStorage.getItem("cvnss4_name"); if(last) els.name.value = last;
195
  syncRoomUI(); els.name.focus({preventScroll:true});
196
  if (qs.get("room") && (last || els.name.value.trim() !== "")) enterChat();