|
13 | 13 | 'subtitle': 'Send requests to your-host/your-path', |
14 | 14 | 'auto_refresh': 'Auto Refresh', |
15 | 15 | 'seconds': 'seconds', |
| 16 | + 'refresh': 'Refresh', |
16 | 17 | 'captured_requests': 'Captured Requests', |
17 | 18 | 'no_requests': 'No requests captured yet.', |
18 | 19 | 'welcome_title': 'Welcome!', |
|
32 | 33 | 'subtitle': '发送请求到 your-host/your-path', |
33 | 34 | 'auto_refresh': '自动刷新', |
34 | 35 | 'seconds': '秒', |
| 36 | + 'refresh': '刷新', |
35 | 37 | 'captured_requests': '已捕获的请求', |
36 | 38 | 'no_requests': '尚未捕获任何请求。', |
37 | 39 | 'welcome_title': '欢迎!', |
|
102 | 104 | </div> |
103 | 105 | <div class="w-1/3 flex justify-end items-center pr-4"> |
104 | 106 | <div class="flex items-center space-x-2"> |
| 107 | + <button id="manualRefreshButton" class="hidden px-3 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors" data-i18n-title="refresh_requests"> |
| 108 | + <svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 109 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> |
| 110 | + </svg> |
| 111 | + <span data-i18n="refresh">刷新</span> |
| 112 | + </button> |
105 | 113 | <input type="checkbox" id="autoRefreshCheckbox" class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"> |
106 | 114 | <label for="autoRefreshCheckbox" class="text-sm text-gray-600" data-i18n="auto_refresh">自动刷新</label> |
107 | 115 | <input type="number" id="refreshIntervalInput" class="w-16 text-sm border-gray-300 rounded-md shadow-sm" min="1" value="5"> |
|
227 | 235 | // --- Auto-refresh logic --- |
228 | 236 | const checkbox = document.getElementById('autoRefreshCheckbox'); |
229 | 237 | const intervalInput = document.getElementById('refreshIntervalInput'); |
| 238 | + const manualRefreshButton = document.getElementById('manualRefreshButton'); |
230 | 239 | let refreshInterval; |
231 | 240 |
|
232 | 241 | function startRefresh() { |
|
244 | 253 | refreshInterval = null; |
245 | 254 | } |
246 | 255 |
|
| 256 | + function toggleManualRefreshButton() { |
| 257 | + if (checkbox.checked) { |
| 258 | + manualRefreshButton.classList.add('hidden'); |
| 259 | + } else { |
| 260 | + manualRefreshButton.classList.remove('hidden'); |
| 261 | + } |
| 262 | + } |
| 263 | + |
247 | 264 | // Function to update only the request list via AJAX |
248 | 265 | function updateRequestList() { |
249 | | - fetch('/api/requests') |
| 266 | + return fetch('/api/requests') |
250 | 267 | .then(response => response.json()) |
251 | 268 | .then(requests => { |
252 | 269 | const requestList = document.querySelector('aside .overflow-y-auto'); |
|
314 | 331 | localStorage.setItem('autoRefreshEnabled', 'false'); |
315 | 332 | stopRefresh(); |
316 | 333 | } |
| 334 | + toggleManualRefreshButton(); |
| 335 | + }); |
| 336 | + |
| 337 | + // Manual refresh button click handler |
| 338 | + let isRefreshing = false; |
| 339 | + const originalButtonContent = ` |
| 340 | + <svg class="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 341 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> |
| 342 | + </svg> |
| 343 | + <span data-i18n="refresh">${translations[currentLang]['refresh']}</span> |
| 344 | + `; |
| 345 | + |
| 346 | + function resetButtonState() { |
| 347 | + manualRefreshButton.innerHTML = originalButtonContent; |
| 348 | + isRefreshing = false; |
| 349 | + } |
| 350 | + |
| 351 | + manualRefreshButton.addEventListener('click', () => { |
| 352 | + if (isRefreshing) return; // Prevent multiple clicks |
| 353 | + |
| 354 | + isRefreshing = true; |
| 355 | + updateRequestList(); |
| 356 | + |
| 357 | + // Add visual feedback |
| 358 | + manualRefreshButton.innerHTML = ` |
| 359 | + <svg class="w-4 h-4 inline mr-1 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 360 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path> |
| 361 | + </svg> |
| 362 | + <span data-i18n="refresh">${translations[currentLang]['refresh']}</span> |
| 363 | + `; |
| 364 | + |
| 365 | + setTimeout(resetButtonState, 500); |
317 | 366 | }); |
318 | 367 |
|
319 | 368 | intervalInput.addEventListener('change', () => { |
|
335 | 384 | if (isEnabled) { |
336 | 385 | startRefresh(); |
337 | 386 | } |
| 387 | + toggleManualRefreshButton(); // Initialize manual refresh button visibility |
338 | 388 |
|
339 | 389 | // --- Collapsible sections logic --- |
340 | 390 | const sections = ['headers', 'body']; |
|
0 commit comments