diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js index dc58f3d9e..0c970efc9 100644 --- a/frontend/public/mockServiceWorker.js +++ b/frontend/public/mockServiceWorker.js @@ -7,8 +7,8 @@ * - Please do NOT modify this file. */ -const PACKAGE_VERSION = '2.14.7' -const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82' +const PACKAGE_VERSION = '2.15.0' +const INTEGRITY_CHECKSUM = '03cb67ac84128e63d7cd722a6e5b7f1e' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() @@ -137,8 +137,18 @@ async function handleRequest(event, requestId, requestInterceptedAt) { if (client && activeClientIds.has(client.id)) { const serializedRequest = await serializeRequest(requestCloneForEvents) + // Omit the body of server-sent event stream responses. + // Cloning such responses would prevent client-side stream cancelations + // from reaching the original stream (a teed stream only cancels its + // source once both of its branches cancel) and would buffer the + // entire stream into the unconsumed clone indefinitely. + const isEventStreamResponse = response.headers + .get('content-type') + ?.toLowerCase() + .startsWith('text/event-stream') + // Clone the response so both the client and the library could consume it. - const responseClone = response.clone() + const responseClone = isEventStreamResponse ? null : response.clone() sendToClient( client, @@ -151,15 +161,17 @@ async function handleRequest(event, requestId, requestInterceptedAt) { ...serializedRequest, }, response: { - type: responseClone.type, - status: responseClone.status, - statusText: responseClone.statusText, - headers: Object.fromEntries(responseClone.headers.entries()), - body: responseClone.body, + type: response.type, + status: response.status, + statusText: response.statusText, + headers: Object.fromEntries(response.headers.entries()), + body: responseClone ? responseClone.body : null, }, }, }, - responseClone.body ? [serializedRequest.body, responseClone.body] : [], + responseClone && responseClone.body + ? [serializedRequest.body, responseClone.body] + : [], ) } diff --git a/frontend/src/layouts/AppSidebar.tsx b/frontend/src/layouts/AppSidebar.tsx index c464fc329..647d67db5 100644 --- a/frontend/src/layouts/AppSidebar.tsx +++ b/frontend/src/layouts/AppSidebar.tsx @@ -219,7 +219,7 @@ export default function AppSidebar() { { key: '/settings#subscription', icon: , label: t('pages.settings.subSettings') }, ]; if (showSubFormats) { - children.push({ key: '/settings#subscription-formats', icon: , label: 'Sub Formats' }); + children.push({ key: '/settings#subscription-formats', icon: , label: t('menu.subFormats') }); } return children; }, [t, showSubFormats]); diff --git a/frontend/src/pages/index/IndexPage.tsx b/frontend/src/pages/index/IndexPage.tsx index 87441e91f..75acbd05d 100644 --- a/frontend/src/pages/index/IndexPage.tsx +++ b/frontend/src/pages/index/IndexPage.tsx @@ -127,7 +127,7 @@ export default function IndexPage() { async function copyConfig() { const ok = await ClipboardManager.copyText(configText || ''); - if (ok) messageApi.success('Copied'); + if (ok) messageApi.success(t('copied')); } function downloadConfig() { diff --git a/frontend/src/pages/index/LogModal.tsx b/frontend/src/pages/index/LogModal.tsx index eccf2b3d3..bbceab2bb 100644 --- a/frontend/src/pages/index/LogModal.tsx +++ b/frontend/src/pages/index/LogModal.tsx @@ -105,14 +105,14 @@ export default function LogModal({ open, onClose }: LogModalProps) {