mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-04 23:29:00 +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: TelegramClient | None = None
|
||||||
self._client_lock = asyncio.Lock()
|
self._client_lock = asyncio.Lock()
|
||||||
self._download_lock = asyncio.Lock()
|
self._download_lock = asyncio.Lock()
|
||||||
|
self._active_stream_message_id: int | None = None
|
||||||
self._message_cache: Dict[int, Tuple[float, object]] = {}
|
self._message_cache: Dict[int, Tuple[float, object]] = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -517,35 +518,7 @@ class TelegramAdapter:
|
|||||||
raise NotImplementedError("Telegram 适配器不支持创建目录。")
|
raise NotImplementedError("Telegram 适配器不支持创建目录。")
|
||||||
|
|
||||||
async def get_thumbnail(self, root: str, rel: str, size: str = "medium"):
|
async def get_thumbnail(self, root: str, rel: str, size: str = "medium"):
|
||||||
try:
|
return None
|
||||||
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
|
|
||||||
|
|
||||||
async def delete(self, root: str, rel: str):
|
async def delete(self, root: str, rel: str):
|
||||||
"""删除一个文件 (即一条消息)"""
|
"""删除一个文件 (即一条消息)"""
|
||||||
@@ -625,11 +598,14 @@ class TelegramAdapter:
|
|||||||
raise HTTPException(status_code=400, detail="Invalid Range header")
|
raise HTTPException(status_code=400, detail="Invalid Range header")
|
||||||
|
|
||||||
headers["Content-Length"] = str(end - start + 1)
|
headers["Content-Length"] = str(end - start + 1)
|
||||||
|
self._active_stream_message_id = message_id
|
||||||
|
|
||||||
async def iterator():
|
async def iterator():
|
||||||
downloaded = 0
|
downloaded = 0
|
||||||
try:
|
try:
|
||||||
limit = end - start + 1
|
limit = end - start + 1
|
||||||
|
if self._active_stream_message_id != message_id:
|
||||||
|
return
|
||||||
async with self._download_lock:
|
async with self._download_lock:
|
||||||
async for chunk in client.iter_download(
|
async for chunk in client.iter_download(
|
||||||
media,
|
media,
|
||||||
@@ -638,6 +614,8 @@ class TelegramAdapter:
|
|||||||
chunk_size=self._download_chunk_size,
|
chunk_size=self._download_chunk_size,
|
||||||
file_size=file_size,
|
file_size=file_size,
|
||||||
):
|
):
|
||||||
|
if self._active_stream_message_id != message_id:
|
||||||
|
return
|
||||||
if not chunk:
|
if not chunk:
|
||||||
continue
|
continue
|
||||||
remaining = limit - downloaded
|
remaining = limit - downloaded
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ function getPluginStylePaths(plugin: PluginItem): string[] {
|
|||||||
return styles.filter((s) => typeof s === 'string' && s.trim().length > 0);
|
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。
|
* 使用 iframe 隔离渲染与样式,避免插件污染宿主 DOM/CSS。
|
||||||
@@ -66,7 +76,10 @@ export const PluginAppHost: React.FC<PluginAppHostProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('message', onMessage);
|
window.addEventListener('message', onMessage);
|
||||||
return () => window.removeEventListener('message', onMessage);
|
return () => {
|
||||||
|
window.removeEventListener('message', onMessage);
|
||||||
|
unloadPluginFrame(iframeRef.current);
|
||||||
|
};
|
||||||
}, [plugin.key]);
|
}, [plugin.key]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -118,7 +131,10 @@ export const PluginAppOpenHost: React.FC<PluginAppOpenHostProps> = ({ plugin, on
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('message', onMessage);
|
window.addEventListener('message', onMessage);
|
||||||
return () => window.removeEventListener('message', onMessage);
|
return () => {
|
||||||
|
window.removeEventListener('message', onMessage);
|
||||||
|
unloadPluginFrame(iframeRef.current);
|
||||||
|
};
|
||||||
}, [plugin.key]);
|
}, [plugin.key]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
+16
-1
@@ -364,12 +364,27 @@ async function main() {
|
|||||||
|
|
||||||
await mountError();
|
await mountError();
|
||||||
|
|
||||||
window.addEventListener('beforeunload', () => {
|
const runCleanup = () => {
|
||||||
try {
|
try {
|
||||||
cleanup?.();
|
cleanup?.();
|
||||||
} catch {
|
} catch {
|
||||||
void 0;
|
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