mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-06-30 19:51:40 +08:00
feat: implement plugin frame cleanup on unload and enhance iframe handling
This commit is contained in:
@@ -91,6 +91,7 @@ class TelegramAdapter:
|
||||
self._client: TelegramClient | None = None
|
||||
self._client_lock = asyncio.Lock()
|
||||
self._download_lock = asyncio.Lock()
|
||||
self._active_stream_message_id: int | None = None
|
||||
self._message_cache: Dict[int, Tuple[float, object]] = {}
|
||||
|
||||
@staticmethod
|
||||
@@ -517,35 +518,7 @@ class TelegramAdapter:
|
||||
raise NotImplementedError("Telegram 适配器不支持创建目录。")
|
||||
|
||||
async def get_thumbnail(self, root: str, rel: str, size: str = "medium"):
|
||||
try:
|
||||
message_id_str, _ = rel.split('_', 1)
|
||||
message_id = int(message_id_str)
|
||||
except (ValueError, IndexError):
|
||||
return None
|
||||
|
||||
try:
|
||||
client = await self._get_connected_client()
|
||||
message = await self._get_cached_message(message_id)
|
||||
if not message:
|
||||
return None
|
||||
|
||||
thumb = self._pick_photo_thumb(self._get_message_thumbs(message))
|
||||
if not thumb:
|
||||
return None
|
||||
|
||||
embedded = getattr(thumb, "bytes", None)
|
||||
if embedded and isinstance(thumb, types.PhotoCachedSize):
|
||||
return bytes(embedded)
|
||||
if embedded and isinstance(thumb, types.PhotoStrippedSize):
|
||||
return utils.stripped_photo_to_jpg(bytes(embedded))
|
||||
|
||||
async with self._download_lock:
|
||||
result = await client.download_media(message, bytes, thumb=thumb)
|
||||
if isinstance(result, (bytes, bytearray)):
|
||||
return bytes(result)
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
return None
|
||||
|
||||
async def delete(self, root: str, rel: str):
|
||||
"""删除一个文件 (即一条消息)"""
|
||||
@@ -625,11 +598,14 @@ class TelegramAdapter:
|
||||
raise HTTPException(status_code=400, detail="Invalid Range header")
|
||||
|
||||
headers["Content-Length"] = str(end - start + 1)
|
||||
self._active_stream_message_id = message_id
|
||||
|
||||
async def iterator():
|
||||
downloaded = 0
|
||||
try:
|
||||
limit = end - start + 1
|
||||
if self._active_stream_message_id != message_id:
|
||||
return
|
||||
async with self._download_lock:
|
||||
async for chunk in client.iter_download(
|
||||
media,
|
||||
@@ -638,6 +614,8 @@ class TelegramAdapter:
|
||||
chunk_size=self._download_chunk_size,
|
||||
file_size=file_size,
|
||||
):
|
||||
if self._active_stream_message_id != message_id:
|
||||
return
|
||||
if not chunk:
|
||||
continue
|
||||
remaining = limit - downloaded
|
||||
|
||||
@@ -24,6 +24,16 @@ function getPluginStylePaths(plugin: PluginItem): string[] {
|
||||
return styles.filter((s) => typeof s === 'string' && s.trim().length > 0);
|
||||
}
|
||||
|
||||
function unloadPluginFrame(iframe: HTMLIFrameElement | null) {
|
||||
if (!iframe) return;
|
||||
try {
|
||||
iframe.contentWindow?.postMessage({ type: 'foxel-plugin:unload' }, window.location.origin);
|
||||
} catch {
|
||||
void 0;
|
||||
}
|
||||
iframe.src = 'about:blank';
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件宿主组件 - 文件打开模式
|
||||
* 使用 iframe 隔离渲染与样式,避免插件污染宿主 DOM/CSS。
|
||||
@@ -66,7 +76,10 @@ export const PluginAppHost: React.FC<PluginAppHostProps> = ({
|
||||
};
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
return () => window.removeEventListener('message', onMessage);
|
||||
return () => {
|
||||
window.removeEventListener('message', onMessage);
|
||||
unloadPluginFrame(iframeRef.current);
|
||||
};
|
||||
}, [plugin.key]);
|
||||
|
||||
return (
|
||||
@@ -118,7 +131,10 @@ export const PluginAppOpenHost: React.FC<PluginAppOpenHostProps> = ({ plugin, on
|
||||
};
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
return () => window.removeEventListener('message', onMessage);
|
||||
return () => {
|
||||
window.removeEventListener('message', onMessage);
|
||||
unloadPluginFrame(iframeRef.current);
|
||||
};
|
||||
}, [plugin.key]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -364,12 +364,27 @@ async function main() {
|
||||
|
||||
await mountError();
|
||||
|
||||
window.addEventListener('beforeunload', () => {
|
||||
const runCleanup = () => {
|
||||
try {
|
||||
cleanup?.();
|
||||
} catch {
|
||||
void 0;
|
||||
}
|
||||
cleanup = null;
|
||||
};
|
||||
|
||||
window.addEventListener('message', (ev) => {
|
||||
if (ev.origin !== window.location.origin) return;
|
||||
if (ev.source !== window.parent) return;
|
||||
const data = ev.data as any;
|
||||
if (!data || typeof data !== 'object') return;
|
||||
if (data.type !== 'foxel-plugin:unload') return;
|
||||
runCleanup();
|
||||
root.innerHTML = '';
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', () => {
|
||||
runCleanup();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user