diff --git a/pkg/miniapp/miniapp.go b/pkg/miniapp/miniapp.go index e7b3b2437..515c1a5ae 100644 --- a/pkg/miniapp/miniapp.go +++ b/pkg/miniapp/miniapp.go @@ -575,6 +575,15 @@ func (h *Handler) apiDev(w http.ResponseWriter, r *http.Request) { writeJSON(w, map[string]any{"error": err.Error()}) return } + case "unregister": + if req.ID == "" { + writeJSON(w, map[string]any{"error": "id is required"}) + return + } + if err := h.UnregisterDevTarget(req.ID); err != nil { + writeJSON(w, map[string]any{"error": err.Error()}) + return + } default: writeJSON(w, map[string]any{"error": "unknown action"}) return diff --git a/pkg/miniapp/static/index.html b/pkg/miniapp/static/index.html index ec8c62837..583b38efe 100644 --- a/pkg/miniapp/static/index.html +++ b/pkg/miniapp/static/index.html @@ -684,6 +684,26 @@ text-overflow: ellipsis; white-space: nowrap; } + .dev-target-delete { + flex-shrink: 0; + width: 24px; + height: 24px; + padding: 6px; + margin: -6px; + margin-left: 8px; + border-radius: 50%; + color: var(--hint); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: color 0.15s, background 0.15s; + -webkit-tap-highlight-color: transparent; + } + .dev-target-delete:active { + color: #ff3b30; + background: rgba(255, 59, 48, 0.1); + } @@ -1346,12 +1366,23 @@ function renderDevFromData(data) { '' + '' + escapeHtml(t.name) + '' + '' + escapeHtml(displayUrl) + '' + + '×' + ''; }).join(''); } // Delegate click on target cards document.getElementById('dev-targets-list').addEventListener('click', function(e) { + var delBtn = e.target.closest('.dev-target-delete'); + if (delBtn) { + e.stopPropagation(); + var id = delBtn.dataset.delId; + var name = delBtn.dataset.delName; + if (confirm('Remove "' + name + '"?')) { + postDevUnregister(id); + } + return; + } var card = e.target.closest('[data-dev-id]'); if (!card) return; postDevAction(card.dataset.devId); @@ -1372,6 +1403,18 @@ async function postDevAction(id) { } catch(e) {} } +async function postDevUnregister(id) { + try { + var res = await fetch(API_BASE + '/miniapp/api/dev?initData=' + encodeURIComponent(initData), { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'unregister', id: id }), + }); + var data = await res.json(); + if (!data.error) renderDevFromData(data); + } catch(e) {} +} + function loadDev() { apiFetch('/miniapp/api/dev').then(renderDevFromData).catch(function() {}); }