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

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +47 -74
index.html CHANGED
@@ -6,53 +6,46 @@
6
  <title>Chat CVNSS4.0</title>
7
  <style>
8
  :root{
9
- /* Giao diện sáng, tối giản */
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 gõ/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 */
@@ -65,9 +58,8 @@
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,7 +67,7 @@
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">
@@ -101,15 +93,11 @@
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 gõ/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,76 +109,61 @@
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"),
132
- name: $("nickname"), join: $("joinBtn"), newRoom: $("newRoomBtn"),
133
- linkArea: $("linkArea"), roomUrl: $("roomUrl"), copy: $("copyBtn"),
134
- hint: $("roomHint"), me: $("meName"), pill: $("roomPill"),
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
-
183
  els.copy.onclick = async ()=>{
184
  try{
185
  await navigator.clipboard?.writeText?.(link);
186
  if(navigator.share){ try{ await navigator.share({title:"Phòng chat CVNSS4.0", url:link}); }catch(_){} }
187
  toast("✅ Đã copy link phòng!");
188
  }catch(_){ toast("⚠️ Không copy được—hãy copy thủ công"); }
189
- els.linkArea.style.display = "none";
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();
 
6
  <title>Chat CVNSS4.0</title>
7
  <style>
8
  :root{
9
+ /* Light theme */
10
  --bg:#f7f9fc; --card:#ffffff; --text:#1f2937; --muted:#6b7280;
11
  --primary:#1a73e8; --danger:#d93025; --accent:#ffeb3b;
12
+ /* CẮT phần đầu tlk.io (icon mây + thanh xanh) — tăng/giảm nếu cần */
13
+ --cut-top: 220px;
14
+ /* Che cột phải */
15
+ --mask-right: clamp(220px, 24vw, 300px);
16
  }
 
17
  *{box-sizing:border-box}
18
+ body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:var(--bg);color:var(--text);display:flex;flex-direction:column;min-height:100vh}
 
19
  header{padding:14px 16px;text-align:center;font-weight:700;background:#fff;border-bottom:1px solid #e5e7eb}
20
+ .card{width:min(980px,94vw);margin:22px auto;background:#fff;border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 6px 18px rgba(0,0,0,.06);padding:18px}
21
+ h2{margin:0 0 6px} .muted{color:var(--muted)}
 
 
22
  .row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
 
23
  input[type=text]{flex:1 1 260px;padding:12px 14px;font-size:16px;border:1px solid #d1d5db;border-radius:10px}
24
  input[type=text]:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(26,115,232,.15)}
 
25
  button{padding:12px 16px;border:0;border-radius:10px;font-weight:700;cursor:pointer}
26
  .btn-red{background:#d93025;color:#ffeb3b}
27
  .btn-ghost{background:#eef2ff;color:#1e3a8a}
28
  .btn-secondary{background:#374151;color:#fff}
29
  .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
30
 
31
+ /* Status gọn */
32
  .status{display:none;align-items:center;gap:10px;padding:10px 12px;border:1px dashed #d1d5db;border-radius:10px;margin-bottom:10px;background:#f9fafb}
33
  .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}
34
  .room-pill{display:inline-block;background:#e8f0fe;color:#174ea6;padding:6px 10px;border-radius:999px}
35
 
36
+ /* Khung chat: CẮT phần đầu an toàn (không chặn click/nhập) */
37
+ .chat-wrap{
38
+ position:relative; border:1px solid #e5e7eb; border-radius:10px; overflow:hidden; background:#fff;
39
+ padding-top: var(--cut-top); /* chừa chỗ cho phần bị đẩy ra */
 
 
 
 
 
40
  }
41
+ #chatFrame{
42
+ display:block; width:100%; height:72vh; min-height:640px; border:0; background:#fff;
43
+ transform: translateY(calc(-1 * var(--cut-top))); /* đẩy phần đầu ra ngoài khung nhìn */
44
+ }
45
+ /* Che cột phải – không chặn click (pointer-events:none) */
46
  .mask-right{
47
+ position:absolute; top:0; right:0; bottom:0; width:var(--mask-right);
48
+ background:#fff; pointer-events:none; box-shadow:-8px 0 10px -10px rgba(0,0,0,.12); z-index:2;
 
49
  }
50
 
51
  /* Link phòng tự ẩn */
 
58
 
59
  .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}
60
  .toast.show{opacity:1}
 
61
  footer{margin-top:auto;text-align:center;color:#6b7280;font-size:13px;padding:16px}
62
+ @media (max-width:820px){ :root{ --mask-right:0px } }
63
  </style>
64
  </head>
65
  <body>
 
67
 
68
  <section id="login" class="card">
69
  <h2>Tham gia phòng chat</h2>
70
+ <p class="muted">Nhập tên → <b>Vào Chat</b> → *(tuỳ chọn)* <b>✨ Tạo phòng bí mật</b>.</p>
71
 
72
  <div class="row" style="margin-top:8px">
73
  <input id="nickname" type="text" placeholder="Nhập tên của bạn…" autocomplete="name">
 
93
  </div>
94
 
95
  <div class="chat-wrap">
96
+ <div class="mask-right" aria-hidden="true"></div>
 
 
 
97
  <iframe id="chatFrame" title="tlk.io chat" referrerpolicy="no-referrer"
98
  allow="clipboard-read; clipboard-write"></iframe>
99
  </div>
100
 
 
101
  <div id="errorBox" class="error-box">
102
  <span class="error-text">⚠️ Không tải được khung chat (trình duyệt/ISP chặn iframe).</span>
103
  <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>
 
109
 
110
  <script>
111
  (() => {
112
+ const qs = new URLSearchParams(location.search);
113
+ let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
 
114
  const base = `${location.origin}${location.pathname}`;
115
 
116
  const $ = id => document.getElementById(id);
117
  const els = {
118
+ login:$("login"), box:$("chatBox"), frame:$("chatFrame"),
119
+ name:$("nickname"), join:$("joinBtn"), newRoom:$("newRoomBtn"),
120
+ linkArea:$("linkArea"), roomUrl:$("roomUrl"), copy:$("copyBtn"),
121
+ hint:$("roomHint"), me:$("meName"), pill:$("roomPill"),
122
+ status:$("statusBar"), toast:$("toast"), err:$("errorBox"), openNew:$("openNew")
123
  };
124
 
125
+ const toast = m=>{ els.toast.textContent=m; els.toast.classList.add("show"); setTimeout(()=>els.toast.classList.remove("show"),1400); };
126
+ const getName = ()=> (els.name.value || localStorage.getItem("cvnss4_name") || "Guest").trim() || "Guest";
127
+ const setName = n=>{ els.me.textContent=n; localStorage.setItem("cvnss4_name", n); };
128
+ const syncRoomUI = ()=>{ els.pill.textContent=room; els.hint.textContent=`(đang ở phòng ${room})`; };
129
+ const tlkUrl = n=> `https://tlk.io/${encodeURIComponent(room)}?nickname=${encodeURIComponent(n)}#embed`;
 
130
 
 
131
  function mountChat(){
132
  const name = getName(); setName(name); syncRoomUI();
133
  els.status.style.display = "flex";
 
134
  const url = tlkUrl(name);
135
+ els.frame.src = url; els.openNew.href = url; els.err.style.display="none";
136
+ const timer = setTimeout(()=>{ els.err.style.display="flex"; }, 6000);
 
 
 
 
137
  els.frame.addEventListener("load", ()=> clearTimeout(timer), {once:true});
138
  }
 
139
  function enterChat(){
140
+ els.login.style.display="none";
141
+ els.box.style.display="block";
142
+ mountChat();
143
  }
144
 
 
145
  els.join.addEventListener("click", enterChat);
146
+ els.name.addEventListener("keydown", e=>{ if(e.key==="Enter") enterChat(); });
147
 
148
+ // Tạo phòng bí mật + copy tự ẩn
149
  els.newRoom.addEventListener("click", async ()=>{
150
  room = `cvnss4-0-${Math.random().toString(36).slice(2,8)}`;
151
+ syncRoomUI(); history.replaceState(null,"",`?room=${room}`);
 
 
152
  const link = `${base}?room=${room}`;
153
+ els.roomUrl.textContent = link; els.linkArea.style.display="flex";
154
+ try{ await navigator.clipboard?.writeText?.(link); toast("✅ Link đã copy!"); }catch(_){}
 
 
155
  setTimeout(()=>{ if(els.linkArea.style.display!=="none") els.linkArea.style.display="none"; }, 9000);
 
156
  els.copy.onclick = async ()=>{
157
  try{
158
  await navigator.clipboard?.writeText?.(link);
159
  if(navigator.share){ try{ await navigator.share({title:"Phòng chat CVNSS4.0", url:link}); }catch(_){} }
160
  toast("✅ Đã copy link phòng!");
161
  }catch(_){ toast("⚠️ Không copy được—hãy copy thủ công"); }
162
+ els.linkArea.style.display="none";
163
  };
164
  });
165
 
166
+ // Prefill + auto-enter khi có tên
167
  const last = localStorage.getItem("cvnss4_name"); if(last) els.name.value = last;
168
  syncRoomUI(); els.name.focus({preventScroll:true});
169
  if (qs.get("room") && (last || els.name.value.trim() !== "")) enterChat();