diff --git a/pkg/miniapp/frontend/src/components/tools/cache-section.tsx b/pkg/miniapp/frontend/src/components/tools/cache-section.tsx
index 86e1f8b5f..671b07c1a 100644
--- a/pkg/miniapp/frontend/src/components/tools/cache-section.tsx
+++ b/pkg/miniapp/frontend/src/components/tools/cache-section.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState, useCallback } from 'preact/hooks';
-import { apiFetch } from '../../hooks/use-api';
+import { apiFetch, apiDelete } from '../../hooks/use-api';
interface CacheEntry {
hash: string;
@@ -51,6 +51,30 @@ export function CacheSection({ active }: CacheSectionProps) {
if (active) load();
}, [active, filter]);
+ const deleteEntry = useCallback(
+ async (hash: string) => {
+ try {
+ await apiDelete('/miniapp/api/cache/' + encodeURIComponent(hash));
+ setExpanded(null);
+ load();
+ } catch {
+ // ignore
+ }
+ },
+ [load],
+ );
+
+ const deleteAll = useCallback(async () => {
+ if (!window.confirm('Delete all cached items?')) return;
+ try {
+ await apiDelete('/miniapp/api/cache');
+ setExpanded(null);
+ load();
+ } catch {
+ // ignore
+ }
+ }, [load]);
+
const formatDate = (iso: string) => {
try {
const d = new Date(iso);
@@ -60,6 +84,8 @@ export function CacheSection({ active }: CacheSectionProps) {
}
};
+ const count = entries ? entries.length : 0;
+
return (
Media Cache
+ {count > 0 && (
+
+ ({count})
+
+ )}
-
+
+ {count > 0 && (
+
+ )}
+
+
@@ -223,6 +277,25 @@ export function CacheSection({ active }: CacheSectionProps) {
{e.result}
)}
+
)}
diff --git a/pkg/miniapp/frontend/src/hooks/use-api.ts b/pkg/miniapp/frontend/src/hooks/use-api.ts
index 136e65e32..c2f90a7ea 100644
--- a/pkg/miniapp/frontend/src/hooks/use-api.ts
+++ b/pkg/miniapp/frontend/src/hooks/use-api.ts
@@ -37,6 +37,16 @@ export async function apiPost(
return res.json();
}
+export async function apiDelete(path: string): Promise {
+ const sep = path.includes('?') ? '&' : '?';
+ const res = await fetch(
+ API_BASE + path + sep + 'initData=' + encodeURIComponent(getInitData()),
+ { method: 'DELETE' },
+ );
+ if (!res.ok) throw new Error('API error: ' + res.status);
+ return res.json();
+}
+
export async function sendCommand(cmd: string): Promise {
if (!cmd.startsWith('/')) return false;
try {
diff --git a/pkg/miniapp/static/dist/app.js b/pkg/miniapp/static/dist/app.js
index bd6f84b57..0a8abba92 100644
--- a/pkg/miniapp/static/dist/app.js
+++ b/pkg/miniapp/static/dist/app.js
@@ -2004,6 +2004,13 @@ https://github.com/highlightjs/highlight.js/issues/2277`);
}
return res.json();
}
+ async function apiDelete(path) {
+ const sep = path.includes("?") ? "&" : "?";
+ const res = await fetch(API_BASE + path + sep + "initData=" + encodeURIComponent(getInitData()), { method: "DELETE" });
+ if (!res.ok)
+ throw new Error("API error: " + res.status);
+ return res.json();
+ }
async function sendCommand(cmd) {
if (!cmd.startsWith("/"))
return false;
@@ -10527,6 +10534,22 @@ Please report this to https://github.com/markedjs/marked.`, e3) {
if (active)
load();
}, [active, filter]);
+ const deleteEntry = q2(async (hash) => {
+ try {
+ await apiDelete("/miniapp/api/cache/" + encodeURIComponent(hash));
+ setExpanded(null);
+ load();
+ } catch {}
+ }, [load]);
+ const deleteAll = q2(async () => {
+ if (!window.confirm("Delete all cached items?"))
+ return;
+ try {
+ await apiDelete("/miniapp/api/cache");
+ setExpanded(null);
+ load();
+ } catch {}
+ }, [load]);
const formatDate = (iso) => {
try {
const d3 = new Date(iso);
@@ -10535,6 +10558,7 @@ Please report this to https://github.com/markedjs/marked.`, e3) {
return iso;
}
};
+ const count = entries ? entries.length : 0;
return /* @__PURE__ */ u5("div", {
class: "card glass",
children: [
@@ -10549,14 +10573,45 @@ Please report this to https://github.com/markedjs/marked.`, e3) {
/* @__PURE__ */ u5("span", {
class: "card-title",
style: { margin: 0 },
- children: "Media Cache"
- }, undefined, false, undefined, this),
- /* @__PURE__ */ u5("button", {
- class: "send-btn",
- style: { padding: "4px 12px", fontSize: "12px" },
- onClick: load,
- children: "Refresh"
- }, undefined, false, undefined, this)
+ children: [
+ "Media Cache",
+ count > 0 && /* @__PURE__ */ u5("span", {
+ style: {
+ fontSize: "11px",
+ fontWeight: 400,
+ color: "var(--hint)",
+ marginLeft: "6px"
+ },
+ children: [
+ "(",
+ count,
+ ")"
+ ]
+ }, undefined, true, undefined, this)
+ ]
+ }, undefined, true, undefined, this),
+ /* @__PURE__ */ u5("div", {
+ style: { display: "flex", gap: "6px" },
+ children: [
+ count > 0 && /* @__PURE__ */ u5("button", {
+ class: "send-btn",
+ style: {
+ padding: "4px 12px",
+ fontSize: "12px",
+ background: "rgba(239,68,68,0.12)",
+ color: "#ef4444"
+ },
+ onClick: deleteAll,
+ children: "Clear All"
+ }, undefined, false, undefined, this),
+ /* @__PURE__ */ u5("button", {
+ class: "send-btn",
+ style: { padding: "4px 12px", fontSize: "12px" },
+ onClick: load,
+ children: "Refresh"
+ }, undefined, false, undefined, this)
+ ]
+ }, undefined, true, undefined, this)
]
}, undefined, true, undefined, this),
/* @__PURE__ */ u5("div", {
@@ -10709,6 +10764,24 @@ Please report this to https://github.com/markedjs/marked.`, e3) {
color: "var(--text)"
},
children: e3.result
+ }, undefined, false, undefined, this),
+ /* @__PURE__ */ u5("button", {
+ style: {
+ marginTop: "8px",
+ padding: "4px 14px",
+ fontSize: "12px",
+ borderRadius: "8px",
+ border: "none",
+ background: "rgba(239,68,68,0.12)",
+ color: "#ef4444",
+ fontWeight: 600,
+ cursor: "pointer"
+ },
+ onClick: (ev) => {
+ ev.stopPropagation();
+ deleteEntry(e3.hash);
+ },
+ children: "Delete"
}, undefined, false, undefined, this)
]
}, undefined, true, undefined, this)