tuhbooh commited on
Commit
662a165
·
verified ·
1 Parent(s): fcb65d7

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +285 -19
index.html CHANGED
@@ -1,19 +1,285 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="vi">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Professional Temp Mail</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
11
+ body {
12
+ font-family: 'Inter', sans-serif;
13
+ background-color: #0f172a;
14
+ color: #f1f5f9;
15
+ }
16
+ .dark-card {
17
+ background: #1e293b;
18
+ border: 1px solid #334155;
19
+ }
20
+ .mail-content-wrapper {
21
+ background: white;
22
+ border-radius: 8px;
23
+ overflow: hidden;
24
+ min-height: 400px;
25
+ }
26
+ .mail-content-wrapper iframe {
27
+ width: 100%;
28
+ border: none;
29
+ height: 100%;
30
+ min-height: 400px;
31
+ }
32
+ .loader { border-top-color: #6366f1; animation: spinner 0.6s linear infinite; }
33
+ @keyframes spinner { to { transform: rotate(360deg); } }
34
+ .progress-bar { transition: width 1s linear; }
35
+
36
+ /* Custom scrollbar */
37
+ ::-webkit-scrollbar { width: 6px; }
38
+ ::-webkit-scrollbar-track { background: #1e293b; }
39
+ ::-webkit-scrollbar-thumb { background: #475569; border-radius: 10px; }
40
+
41
+ /* Text content formatting */
42
+ .raw-text-content {
43
+ color: #1e293b;
44
+ line-height: 1.6;
45
+ font-family: 'Inter', sans-serif;
46
+ white-space: pre-wrap;
47
+ word-break: break-word;
48
+ }
49
+ .raw-text-content a {
50
+ color: #4f46e5;
51
+ text-decoration: underline;
52
+ }
53
+ </style>
54
+ </head>
55
+ <body class="min-h-screen py-10 px-4">
56
+ <div class="max-w-4xl mx-auto">
57
+ <!-- Header -->
58
+ <div class="mb-8">
59
+ <h1 class="text-3xl font-bold text-white flex items-center gap-3">
60
+ <i class="fa-solid fa-shield-halved text-indigo-500"></i> Temp Mail Service
61
+ </h1>
62
+ <p class="text-slate-400 mt-1">Dịch vụ email tạm thời bảo mật và ẩn danh</p>
63
+ </div>
64
+
65
+ <!-- Mail Creation Area -->
66
+ <div class="dark-card rounded-2xl p-6 shadow-2xl mb-6">
67
+ <label class="block text-sm font-medium text-slate-400 mb-2 uppercase tracking-wider">Địa chỉ email hiện tại</label>
68
+ <div class="flex flex-col sm:flex-row gap-3">
69
+ <div class="relative flex-grow">
70
+ <input type="text" id="emailAddr" readonly placeholder="Đang khởi tạo..."
71
+ class="w-full bg-slate-900 border border-slate-700 rounded-xl py-3 px-4 pr-12 font-mono text-indigo-400 focus:outline-none focus:border-indigo-500">
72
+ <button onclick="copyEmail()" class="absolute right-3 top-3 text-slate-500 hover:text-indigo-400 transition-colors">
73
+ <i class="fa-regular fa-copy text-xl"></i>
74
+ </button>
75
+ </div>
76
+ <button onclick="createNewAccount()" class="bg-slate-700 hover:bg-slate-600 text-white font-semibold py-3 px-6 rounded-xl flex items-center justify-center gap-2 transition-all">
77
+ <i class="fa-solid fa-rotate"></i> Đổi địa chỉ
78
+ </button>
79
+ </div>
80
+ <div id="copyToast" class="hidden text-xs text-emerald-400 mt-2 font-medium text-center">Đã sao chép địa chỉ vào clipboard</div>
81
+ </div>
82
+
83
+ <!-- Controls & Status -->
84
+ <div class="flex items-center justify-between mb-4 px-2">
85
+ <div class="flex items-center gap-3">
86
+ <h2 class="text-xl font-bold text-slate-200">Hộp thư đến</h2>
87
+ <div id="refreshLoader" class="hidden w-5 h-5 border-2 border-slate-600 loader rounded-full"></div>
88
+ </div>
89
+ <div class="flex items-center gap-2 text-sm text-slate-500">
90
+ <span id="timerText">Làm mới sau 5s</span>
91
+ <div class="w-20 h-1.5 bg-slate-800 rounded-full overflow-hidden">
92
+ <div id="timerBar" class="progress-bar h-full bg-indigo-500" style="width: 100%"></div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Inbox List -->
98
+ <div id="inboxContainer" class="space-y-3">
99
+ <!-- Empty State -->
100
+ <div id="emptyState" class="text-center py-20 dark-card rounded-2xl border-dashed border-2 border-slate-700">
101
+ <i class="fa-solid fa-inbox text-5xl text-slate-700 mb-4"></i>
102
+ <p class="text-slate-500">Đang chờ thư mới...</p>
103
+ </div>
104
+ </div>
105
+ </div>
106
+
107
+ <!-- Modal Xem Thư (Reader) -->
108
+ <div id="mailModal" class="fixed inset-0 bg-slate-950/80 hidden z-50 flex items-center justify-center p-4">
109
+ <div class="dark-card w-full max-w-4xl rounded-2xl shadow-2xl flex flex-col max-h-[90vh]">
110
+ <div class="p-4 border-b border-slate-700 flex justify-between items-center">
111
+ <h3 class="font-bold text-slate-200 truncate pr-4" id="modalSubject">Tiêu đề thư</h3>
112
+ <button onclick="closeMail()" class="text-slate-500 hover:text-white text-2xl">&times;</button>
113
+ </div>
114
+ <div class="p-4 bg-slate-900/50 border-b border-slate-700 text-sm">
115
+ <div id="modalFrom" class="text-indigo-400 font-medium"></div>
116
+ <div id="modalTime" class="text-slate-500 text-xs mt-1"></div>
117
+ </div>
118
+ <div class="p-4 overflow-auto flex-grow bg-slate-100 rounded-b-2xl">
119
+ <div id="modalBody" class="mail-content-wrapper"></div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+
124
+ <script>
125
+ const API = "https://api.mail.tm";
126
+ let currentToken = "";
127
+ let currentEmail = "";
128
+ let refreshSec = 5;
129
+
130
+ async function init() {
131
+ await createNewAccount();
132
+ startTimer();
133
+ }
134
+
135
+ async function createNewAccount() {
136
+ try {
137
+ const domains = await fetch(`${API}/domains`).then(r => r.json());
138
+ const domain = domains['hydra:member'][0].domain;
139
+ const user = Math.random().toString(36).substring(2, 12);
140
+ const address = `${user}@${domain}`;
141
+ const password = "password123";
142
+
143
+ await fetch(`${API}/accounts`, {
144
+ method: 'POST',
145
+ headers: {'Content-Type': 'application/json'},
146
+ body: JSON.stringify({address, password})
147
+ });
148
+
149
+ const tokenData = await fetch(`${API}/token`, {
150
+ method: 'POST',
151
+ headers: {'Content-Type': 'application/json'},
152
+ body: JSON.stringify({address, password})
153
+ }).then(r => r.json());
154
+
155
+ currentToken = tokenData.token;
156
+ currentEmail = address;
157
+ document.getElementById('emailAddr').value = address;
158
+
159
+ document.getElementById('inboxContainer').innerHTML = `
160
+ <div id="emptyState" class="text-center py-20 dark-card rounded-2xl border-dashed border-2 border-slate-700">
161
+ <i class="fa-solid fa-inbox text-5xl text-slate-700 mb-4"></i>
162
+ <p class="text-slate-500">Đang chờ thư mới...</p>
163
+ </div>
164
+ `;
165
+ checkInbox();
166
+ } catch (err) { console.error(err); }
167
+ }
168
+
169
+ async function checkInbox() {
170
+ if (!currentToken) return;
171
+ document.getElementById('refreshLoader').classList.remove('hidden');
172
+ try {
173
+ const res = await fetch(`${API}/messages`, {
174
+ headers: {'Authorization': `Bearer ${currentToken}`}
175
+ }).then(r => r.json());
176
+ renderInbox(res['hydra:member']);
177
+ } catch (err) { console.error(err); }
178
+ document.getElementById('refreshLoader').classList.add('hidden');
179
+ }
180
+
181
+ function renderInbox(msgs) {
182
+ const container = document.getElementById('inboxContainer');
183
+ const empty = document.getElementById('emptyState');
184
+ if (!msgs || msgs.length === 0) return;
185
+
186
+ if (empty) empty.remove();
187
+ const currentIds = Array.from(container.querySelectorAll('.mail-item')).map(m => m.dataset.id);
188
+
189
+ msgs.forEach(m => {
190
+ if (!currentIds.includes(m.id)) {
191
+ const div = document.createElement('div');
192
+ div.className = "mail-item bg-slate-800 p-4 rounded-xl border border-slate-700 hover:border-indigo-500 transition-all cursor-pointer flex justify-between items-center group shadow-sm animate-fade-in";
193
+ div.dataset.id = m.id;
194
+ div.onclick = () => openMail(m.id);
195
+ div.innerHTML = `
196
+ <div class="flex-grow mr-4 overflow-hidden">
197
+ <div class="flex items-center gap-2 mb-1">
198
+ <span class="text-xs font-bold text-indigo-400 uppercase tracking-tighter truncate">${m.from.address}</span>
199
+ <span class="text-[10px] text-slate-500 whitespace-nowrap">${new Date(m.createdAt).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>
200
+ </div>
201
+ <div class="font-semibold text-slate-200 truncate">${m.subject || '(Không có tiêu đề)'}</div>
202
+ </div>
203
+ <i class="fa-solid fa-arrow-right-long text-slate-600 group-hover:text-indigo-400 group-hover:translate-x-1 transition-all"></i>
204
+ `;
205
+ container.prepend(div);
206
+ }
207
+ });
208
+ }
209
+
210
+ async function openMail(id) {
211
+ const modal = document.getElementById('mailModal');
212
+ const bodyWrapper = document.getElementById('modalBody');
213
+ bodyWrapper.innerHTML = '<div class="flex justify-center p-20"><div class="loader w-10 h-10 border-4 rounded-full"></div></div>';
214
+ modal.classList.remove('hidden');
215
+
216
+ try {
217
+ const m = await fetch(`${API}/messages/${id}`, {
218
+ headers: {'Authorization': `Bearer ${currentToken}`}
219
+ }).then(r => r.json());
220
+
221
+ document.getElementById('modalSubject').innerText = m.subject || 'No Subject';
222
+ document.getElementById('modalFrom').innerText = `Từ: ${m.from.address}`;
223
+ document.getElementById('modalTime').innerText = new Date(m.createdAt).toLocaleString();
224
+
225
+ if (m.html && m.html.length > 0) {
226
+ bodyWrapper.innerHTML = `<iframe id="mailIframe" title="Email Content"></iframe>`;
227
+ const iframe = document.getElementById('mailIframe');
228
+ const doc = iframe.contentWindow.document;
229
+ doc.open();
230
+ doc.write(`
231
+ <style>
232
+ body { font-family: 'Inter', -apple-system, sans-serif; line-height: 1.6; color: #333; }
233
+ img { max-width: 100%; height: auto; }
234
+ a { color: #4f46e5; }
235
+ </style>
236
+ ${m.html[0]}
237
+ `);
238
+ doc.close();
239
+
240
+ // Auto-height adjustment
241
+ iframe.onload = () => {
242
+ iframe.style.height = doc.body.scrollHeight + 'px';
243
+ };
244
+ } else {
245
+ // Fallback for Text/Markdown-like content
246
+ const textWithLinks = m.text.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>');
247
+ bodyWrapper.innerHTML = `
248
+ <div class="p-6 bg-white h-full overflow-auto">
249
+ <div class="raw-text-content">${textWithLinks}</div>
250
+ </div>
251
+ `;
252
+ }
253
+ } catch (err) {
254
+ bodyWrapper.innerHTML = '<p class="text-red-500 text-center p-10">Lỗi tải nội dung thư. Vui lòng thử lại.</p>';
255
+ }
256
+ }
257
+
258
+ function closeMail() { document.getElementById('mailModal').classList.add('hidden'); }
259
+
260
+ function copyEmail() {
261
+ const el = document.getElementById('emailAddr');
262
+ el.select();
263
+ document.execCommand('copy');
264
+ const toast = document.getElementById('copyToast');
265
+ toast.classList.remove('hidden');
266
+ setTimeout(() => toast.classList.add('hidden'), 2000);
267
+ }
268
+
269
+ function startTimer() {
270
+ let count = refreshSec;
271
+ const bar = document.getElementById('timerBar');
272
+ setInterval(() => {
273
+ count--;
274
+ if (bar) bar.style.width = (count / refreshSec * 100) + "%";
275
+ if (count <= 0) {
276
+ checkInbox();
277
+ count = refreshSec;
278
+ }
279
+ }, 1000);
280
+ }
281
+
282
+ window.onload = init;
283
+ </script>
284
+ </body>
285
+ </html>