File size: 8,572 Bytes
a148270
 
 
9215025
 
 
 
6bb9ef5
10fcbe3
b4ebf19
6bb9ef5
10fcbe3
 
 
 
6bb9ef5
 
10fcbe3
69abab1
10fcbe3
 
69abab1
 
 
 
 
 
 
fbadd81
 
10fcbe3
69abab1
 
 
fbadd81
10fcbe3
 
 
 
58b0a9a
10fcbe3
 
 
 
 
b4ebf19
10fcbe3
 
b4ebf19
fbadd81
17b561f
69abab1
 
17b561f
96c5562
69abab1
17b561f
58b0a9a
69abab1
96c5562
69abab1
10fcbe3
9215025
a148270
 
f89aa8c
 
7153f47
f89aa8c
10fcbe3
69abab1
17b561f
9215025
1fef416
f89aa8c
69abab1
9215025
 
 
f89aa8c
69abab1
1fef416
7153f47
6bb9ef5
17b561f
f89aa8c
7153f47
f89aa8c
9215025
 
6bb9ef5
 
 
17b561f
 
10fcbe3
b4ebf19
 
17b561f
 
 
96c5562
17b561f
f89aa8c
7153f47
f89aa8c
9215025
 
f89aa8c
 
9215025
10fcbe3
 
6bb9ef5
 
96c5562
9215025
10fcbe3
 
 
 
 
1fef416
 
10fcbe3
 
 
 
 
a48e66f
17b561f
 
7c50ff6
17b561f
10fcbe3
 
96c5562
7c50ff6
 
10fcbe3
 
 
1fef416
f89aa8c
1fef416
10fcbe3
1fef416
10fcbe3
6bb9ef5
9215025
10fcbe3
6bb9ef5
10fcbe3
 
fbadd81
6bb9ef5
1fef416
9215025
 
300677f
9215025
10fcbe3
8348c3d
9215025
1fef416
10fcbe3
6bb9ef5
7c50ff6
17b561f
9215025
f89aa8c
a148270
d70ef42
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Chat CVNSS4.0</title>
<style>
  :root{
    /* Light theme */
    --bg:#f7f9fc; --card:#ffffff; --text:#1f2937; --muted:#6b7280;
    --primary:#1a73e8; --danger:#d93025; --accent:#ffeb3b;
    /* CẮT phần đầu tlk.io (icon mây + thanh xanh) — tăng/giảm nếu cần */
    --cut-top: 220px;
    /* Che cột phải */
    --mask-right: clamp(220px, 24vw, 300px);
  }
  *{box-sizing:border-box}
  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}
  header{padding:14px 16px;text-align:center;font-weight:700;background:#fff;border-bottom:1px solid #e5e7eb}
  .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}
  h2{margin:0 0 6px} .muted{color:var(--muted)}
  .row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
  input[type=text]{flex:1 1 260px;padding:12px 14px;font-size:16px;border:1px solid #d1d5db;border-radius:10px}
  input[type=text]:focus{outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(26,115,232,.15)}
  button{padding:12px 16px;border:0;border-radius:10px;font-weight:700;cursor:pointer}
  .btn-red{background:#d93025;color:#ffeb3b}
  .btn-ghost{background:#eef2ff;color:#1e3a8a}
  .btn-secondary{background:#374151;color:#fff}
  .mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}

  /* Status gọn */
  .status{display:none;align-items:center;gap:10px;padding:10px 12px;border:1px dashed #d1d5db;border-radius:10px;margin-bottom:10px;background:#f9fafb}
  .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}
  .room-pill{display:inline-block;background:#e8f0fe;color:#174ea6;padding:6px 10px;border-radius:999px}

  /* Khung chat: CẮT phần đầu an toàn (không chặn click/nhập) */
  .chat-wrap{
    position:relative; border:1px solid #e5e7eb; border-radius:10px; overflow:hidden; background:#fff;
    padding-top: var(--cut-top);              /* chừa chỗ cho phần bị đẩy ra */
  }
  #chatFrame{
    display:block; width:100%; height:72vh; min-height:640px; border:0; background:#fff;
    transform: translateY(calc(-1 * var(--cut-top))); /* đẩy phần đầu ra ngoài khung nhìn */
  }
  /* Che cột phải – không chặn click (pointer-events:none) */
  .mask-right{
    position:absolute; top:0; right:0; bottom:0; width:var(--mask-right);
    background:#fff; pointer-events:none; box-shadow:-8px 0 10px -10px rgba(0,0,0,.12); z-index:2;
  }

  /* Link phòng tự ẩn */
  .links{display:none;gap:8px;align-items:center;flex-wrap:wrap;margin-top:10px}
  .link-badge{background:#f3f4f6;border:1px solid #e5e7eb;color:#111827;padding:6px 8px;border-radius:8px}

  /* Fallback khi iframe bị chặn */
  .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}
  .error-text{color:#991b1b}

  .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}
  .toast.show{opacity:1}
  footer{margin-top:auto;text-align:center;color:#6b7280;font-size:13px;padding:16px}
  @media (max-width:820px){ :root{ --mask-right:0px } }
</style>
</head>
<body>
<header>💬 Chat CVNSS4.0</header>

<section id="login" class="card">
  <h2>Tham gia phòng chat</h2>
  <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>

  <div class="row" style="margin-top:8px">
    <input id="nickname" type="text" placeholder="Nhập tên của bạn…" autocomplete="name">
    <button id="joinBtn" class="btn-red">Vào Chat</button>
  </div>

  <div class="row" style="margin-top:10px">
    <button id="newRoomBtn" class="btn-ghost">✨ Tạo phòng bí mật</button>
    <span id="roomHint" class="muted"></span>
  </div>

  <div id="linkArea" class="links" aria-live="polite">
    <span>🔗 Link phòng:</span>
    <span id="roomUrl" class="link-badge mono"></span>
    <button id="copyBtn" class="btn-secondary">📋 Copy</button>
  </div>
</section>

<section id="chatBox" class="card" style="display:none">
  <div class="status" id="statusBar">
    <span class="me-pill">👤 <span id="meName">Guest</span></span>
    <span class="room-pill">Phòng: <span id="roomPill" class="mono"></span></span>
  </div>

  <div class="chat-wrap">
    <div class="mask-right" aria-hidden="true"></div>
    <iframe id="chatFrame" title="tlk.io chat" referrerpolicy="no-referrer"
            allow="clipboard-read; clipboard-write"></iframe>
  </div>

  <div id="errorBox" class="error-box">
    <span class="error-text">⚠️ Không tải được khung chat (trình duyệt/ISP chặn iframe).</span>
    <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>
  </div>
</section>

<div id="toast" class="toast">Đã copy!</div>
<footer>Nguồn: Sản phẩm thử nghiệm của Team CVNSS4.0 • Đóng tab là xóa hết dữ liệu ✅</footer>

<script>
(() => {
  const qs = new URLSearchParams(location.search);
  let room = (qs.get("room") || "cvnss4-0").trim().toLowerCase();
  const base = `${location.origin}${location.pathname}`;

  const $ = id => document.getElementById(id);
  const els = {
    login:$("login"), box:$("chatBox"), frame:$("chatFrame"),
    name:$("nickname"), join:$("joinBtn"), newRoom:$("newRoomBtn"),
    linkArea:$("linkArea"), roomUrl:$("roomUrl"), copy:$("copyBtn"),
    hint:$("roomHint"), me:$("meName"), pill:$("roomPill"),
    status:$("statusBar"), toast:$("toast"), err:$("errorBox"), openNew:$("openNew")
  };

  const toast = m=>{ els.toast.textContent=m; els.toast.classList.add("show"); setTimeout(()=>els.toast.classList.remove("show"),1400); };
  const getName = ()=> (els.name.value || localStorage.getItem("cvnss4_name") || "Guest").trim() || "Guest";
  const setName = n=>{ els.me.textContent=n; localStorage.setItem("cvnss4_name", n); };
  const syncRoomUI = ()=>{ els.pill.textContent=room; els.hint.textContent=`(đang ở phòng ${room})`; };
  const tlkUrl = n=> `https://tlk.io/${encodeURIComponent(room)}?nickname=${encodeURIComponent(n)}#embed`;

  function mountChat(){
    const name = getName(); setName(name); syncRoomUI();
    els.status.style.display = "flex";
    const url = tlkUrl(name);
    els.frame.src = url; els.openNew.href = url; els.err.style.display="none";
    const timer = setTimeout(()=>{ els.err.style.display="flex"; }, 6000);
    els.frame.addEventListener("load", ()=> clearTimeout(timer), {once:true});
  }
  function enterChat(){
    els.login.style.display="none";
    els.box.style.display="block";
    mountChat();
  }

  els.join.addEventListener("click", enterChat);
  els.name.addEventListener("keydown", e=>{ if(e.key==="Enter") enterChat(); });

  // Tạo phòng bí mật + copy tự ẩn
  els.newRoom.addEventListener("click", async ()=>{
    room = `cvnss4-0-${Math.random().toString(36).slice(2,8)}`;
    syncRoomUI(); history.replaceState(null,"",`?room=${room}`);
    const link = `${base}?room=${room}`;
    els.roomUrl.textContent = link; els.linkArea.style.display="flex";
    try{ await navigator.clipboard?.writeText?.(link); toast("✅ Link đã copy!"); }catch(_){}
    setTimeout(()=>{ if(els.linkArea.style.display!=="none") els.linkArea.style.display="none"; }, 9000);
    els.copy.onclick = async ()=>{
      try{
        await navigator.clipboard?.writeText?.(link);
        if(navigator.share){ try{ await navigator.share({title:"Phòng chat CVNSS4.0", url:link}); }catch(_){} }
        toast("✅ Đã copy link phòng!");
      }catch(_){ toast("⚠️ Không copy được—hãy copy thủ công"); }
      els.linkArea.style.display="none";
    };
  });

  // Prefill + auto-enter khi có tên
  const last = localStorage.getItem("cvnss4_name"); if(last) els.name.value = last;
  syncRoomUI(); els.name.focus({preventScroll:true});
  if (qs.get("room") && (last || els.name.value.trim() !== "")) enterChat();
})();
</script>
</body>
</html>