Skip to content

Commit deddbdf

Browse files
committed
feat: implement plugin frame cleanup on unload and enhance iframe handling
1 parent bd24d7e commit deddbdf

3 files changed

Lines changed: 41 additions & 32 deletions

File tree

domain/adapters/providers/telegram.py

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def __init__(self, record: StorageAdapter):
9191
self._client: TelegramClient | None = None
9292
self._client_lock = asyncio.Lock()
9393
self._download_lock = asyncio.Lock()
94+
self._active_stream_message_id: int | None = None
9495
self._message_cache: Dict[int, Tuple[float, object]] = {}
9596

9697
@staticmethod
@@ -517,35 +518,7 @@ async def mkdir(self, root: str, rel: str):
517518
raise NotImplementedError("Telegram 适配器不支持创建目录。")
518519

519520
async def get_thumbnail(self, root: str, rel: str, size: str = "medium"):
520-
try:
521-
message_id_str, _ = rel.split('_', 1)
522-
message_id = int(message_id_str)
523-
except (ValueError, IndexError):
524-
return None
525-
526-
try:
527-
client = await self._get_connected_client()
528-
message = await self._get_cached_message(message_id)
529-
if not message:
530-
return None
531-
532-
thumb = self._pick_photo_thumb(self._get_message_thumbs(message))
533-
if not thumb:
534-
return None
535-
536-
embedded = getattr(thumb, "bytes", None)
537-
if embedded and isinstance(thumb, types.PhotoCachedSize):
538-
return bytes(embedded)
539-
if embedded and isinstance(thumb, types.PhotoStrippedSize):
540-
return utils.stripped_photo_to_jpg(bytes(embedded))
541-
542-
async with self._download_lock:
543-
result = await client.download_media(message, bytes, thumb=thumb)
544-
if isinstance(result, (bytes, bytearray)):
545-
return bytes(result)
546-
return None
547-
except Exception:
548-
return None
521+
return None
549522

550523
async def delete(self, root: str, rel: str):
551524
"""删除一个文件 (即一条消息)"""
@@ -625,11 +598,14 @@ async def stream_file(self, root: str, rel: str, range_header: str | None):
625598
raise HTTPException(status_code=400, detail="Invalid Range header")
626599

627600
headers["Content-Length"] = str(end - start + 1)
601+
self._active_stream_message_id = message_id
628602

629603
async def iterator():
630604
downloaded = 0
631605
try:
632606
limit = end - start + 1
607+
if self._active_stream_message_id != message_id:
608+
return
633609
async with self._download_lock:
634610
async for chunk in client.iter_download(
635611
media,
@@ -638,6 +614,8 @@ async def iterator():
638614
chunk_size=self._download_chunk_size,
639615
file_size=file_size,
640616
):
617+
if self._active_stream_message_id != message_id:
618+
return
641619
if not chunk:
642620
continue
643621
remaining = limit - downloaded

web/src/apps/PluginHost/index.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ function getPluginStylePaths(plugin: PluginItem): string[] {
2424
return styles.filter((s) => typeof s === 'string' && s.trim().length > 0);
2525
}
2626

27+
function unloadPluginFrame(iframe: HTMLIFrameElement | null) {
28+
if (!iframe) return;
29+
try {
30+
iframe.contentWindow?.postMessage({ type: 'foxel-plugin:unload' }, window.location.origin);
31+
} catch {
32+
void 0;
33+
}
34+
iframe.src = 'about:blank';
35+
}
36+
2737
/**
2838
* 插件宿主组件 - 文件打开模式
2939
* 使用 iframe 隔离渲染与样式,避免插件污染宿主 DOM/CSS。
@@ -66,7 +76,10 @@ export const PluginAppHost: React.FC<PluginAppHostProps> = ({
6676
};
6777

6878
window.addEventListener('message', onMessage);
69-
return () => window.removeEventListener('message', onMessage);
79+
return () => {
80+
window.removeEventListener('message', onMessage);
81+
unloadPluginFrame(iframeRef.current);
82+
};
7083
}, [plugin.key]);
7184

7285
return (
@@ -118,7 +131,10 @@ export const PluginAppOpenHost: React.FC<PluginAppOpenHostProps> = ({ plugin, on
118131
};
119132

120133
window.addEventListener('message', onMessage);
121-
return () => window.removeEventListener('message', onMessage);
134+
return () => {
135+
window.removeEventListener('message', onMessage);
136+
unloadPluginFrame(iframeRef.current);
137+
};
122138
}, [plugin.key]);
123139

124140
return (

web/src/plugin-frame.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,12 +364,27 @@ async function main() {
364364

365365
await mountError();
366366

367-
window.addEventListener('beforeunload', () => {
367+
const runCleanup = () => {
368368
try {
369369
cleanup?.();
370370
} catch {
371371
void 0;
372372
}
373+
cleanup = null;
374+
};
375+
376+
window.addEventListener('message', (ev) => {
377+
if (ev.origin !== window.location.origin) return;
378+
if (ev.source !== window.parent) return;
379+
const data = ev.data as any;
380+
if (!data || typeof data !== 'object') return;
381+
if (data.type !== 'foxel-plugin:unload') return;
382+
runCleanup();
383+
root.innerHTML = '';
384+
});
385+
386+
window.addEventListener('beforeunload', () => {
387+
runCleanup();
373388
});
374389
}
375390

0 commit comments

Comments
 (0)