fix: images did not get cleared after clicking stop
This commit is contained in:
@@ -107,7 +107,6 @@ export default function useZoom(props: {
|
|||||||
if (isLoadingMaskRef.current) {
|
if (isLoadingMaskRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
// stop
|
// stop
|
||||||
handleZoom(event);
|
handleZoom(event);
|
||||||
updateCursorSize();
|
updateCursorSize();
|
||||||
|
|||||||
@@ -152,5 +152,7 @@ export default {
|
|||||||
'1. After selection, no further masking can be drawn; therefore, you should draw the mask first and then check the option.\n 2. Once a mask image is uploaded, no further masks can be generated.',
|
'1. After selection, no further masking can be drawn; therefore, you should draw the mask first and then check the option.\n 2. Once a mask image is uploaded, no further masks can be generated.',
|
||||||
'playground.model.noavailable.tips2':
|
'playground.model.noavailable.tips2':
|
||||||
'If the expected model isn’t showing up, make sure it’s running and correctly categorized. If the category is incorrect, you can manually adjust it in the model’s settings.',
|
'If the expected model isn’t showing up, make sure it’s running and correctly categorized. If the category is incorrect, you can manually adjust it in the model’s settings.',
|
||||||
'playground.rerank.query.validate': 'The query is required.'
|
'playground.rerank.query.validate': 'The query is required.',
|
||||||
|
'playground.image.generate.error':
|
||||||
|
'Something went wrong. The image could not be generated.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -155,9 +155,12 @@ export default {
|
|||||||
'1. 選択後は追加のマスクを描画できません。そのため、最初にマスクを描画してからオプションを選択してください。\n 2. マスク画像をアップロードすると、追加のマスクを生成することはできません。',
|
'1. 選択後は追加のマスクを描画できません。そのため、最初にマスクを描画してからオプションを選択してください。\n 2. マスク画像をアップロードすると、追加のマスクを生成することはできません。',
|
||||||
'playground.model.noavailable.tips2':
|
'playground.model.noavailable.tips2':
|
||||||
'期待するモデルが表示されない場合は、モデルが実行中で正しく分類されていることを確認してください。カテゴリが間違っている場合は、モデルの設定で手動で調整できます。',
|
'期待するモデルが表示されない場合は、モデルが実行中で正しく分類されていることを確認してください。カテゴリが間違っている場合は、モデルの設定で手動で調整できます。',
|
||||||
'playground.rerank.query.validate': 'The query is required.'
|
'playground.rerank.query.validate': 'The query is required.',
|
||||||
|
'playground.image.generate.error':
|
||||||
|
'Something went wrong. The image could not be generated.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'playground.rerank.query.validate': 'The query is required.'
|
// 1. 'playground.rerank.query.validate': 'The query is required.'
|
||||||
|
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -149,9 +149,12 @@ export default {
|
|||||||
'1. После выделения области создание маски станет недоступным; поэтому сначала нарисуйте маску, а затем активируйте опцию. \n 2. После загрузки изображения маски создание новых масок невозможно.',
|
'1. После выделения области создание маски станет недоступным; поэтому сначала нарисуйте маску, а затем активируйте опцию. \n 2. После загрузки изображения маски создание новых масок невозможно.',
|
||||||
'playground.model.noavailable.tips2':
|
'playground.model.noavailable.tips2':
|
||||||
'Если нужная модель не отображается, убедитесь, что она запущена и ей присвоена правильная категория. Если категория указана неверно, её можно изменить вручную в настройках модели.',
|
'Если нужная модель не отображается, убедитесь, что она запущена и ей присвоена правильная категория. Если категория указана неверно, её можно изменить вручную в настройках модели.',
|
||||||
'playground.rerank.query.validate': 'The query is required.'
|
'playground.rerank.query.validate': 'The query is required.',
|
||||||
|
'playground.image.generate.error':
|
||||||
|
'Something went wrong. The image could not be generated.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'playground.rerank.query.validate': 'The query is required.'
|
// 1. 'playground.rerank.query.validate': 'The query is required.'
|
||||||
|
// 2. 'playground.image.generate.error': 'Something went wrong. The image could not be generated.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -146,5 +146,6 @@ export default {
|
|||||||
'1. 选择后,将不可再绘制遮罩;因此,你应该先绘制遮罩然后再勾选.\n 2. 当上传了遮罩图片,将不可再生成遮罩',
|
'1. 选择后,将不可再绘制遮罩;因此,你应该先绘制遮罩然后再勾选.\n 2. 当上传了遮罩图片,将不可再生成遮罩',
|
||||||
'playground.model.noavailable.tips2':
|
'playground.model.noavailable.tips2':
|
||||||
'若预期的模型未显示,请检查模型是否已正常运行并被正确分类。如分类不正确,请编辑模型并手动调整其类别。',
|
'若预期的模型未显示,请检查模型是否已正常运行并被正确分类。如分类不正确,请编辑模型并手动调整其类别。',
|
||||||
'playground.rerank.query.validate': '查询内容不能为空'
|
'playground.rerank.query.validate': '查询内容不能为空',
|
||||||
|
'playground.image.generate.error': '出了一点问题,图片未能生成。'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (manual) {
|
if (manual) {
|
||||||
form.current?.form?.resetFields(resetFieldsByModel);
|
form.current?.form?.setFieldsValue(defaultFormValues);
|
||||||
}
|
}
|
||||||
// If the item is empty
|
// If the item is empty
|
||||||
setIsGGUF(item.isGGUF);
|
setIsGGUF(item.isGGUF);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
fetchChunkedDataPostFormData,
|
fetchChunkedDataPostFormData,
|
||||||
readLargeStreamData as readStreamData
|
readLargeStreamData as readStreamData
|
||||||
} from '@/utils/fetch-chunk-data';
|
} from '@/utils/fetch-chunk-data';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { CREAT_IMAGE_API, EDIT_IMAGE_API } from '../apis';
|
import { CREAT_IMAGE_API, EDIT_IMAGE_API } from '../apis';
|
||||||
@@ -12,6 +13,7 @@ import { CREAT_IMAGE_API, EDIT_IMAGE_API } from '../apis';
|
|||||||
const ODD_STRING = 'AAAABJRU5ErkJgg===';
|
const ODD_STRING = 'AAAABJRU5ErkJgg===';
|
||||||
|
|
||||||
export default function useTextImage(props: any) {
|
export default function useTextImage(props: any) {
|
||||||
|
const intl = useIntl();
|
||||||
const { scroller, paramsRef, chunkFields, API } = props;
|
const { scroller, paramsRef, chunkFields, API } = props;
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [tokenResult, setTokenResult] = useState<any>(null);
|
const [tokenResult, setTokenResult] = useState<any>(null);
|
||||||
@@ -34,6 +36,8 @@ export default function useTextImage(props: any) {
|
|||||||
const requestToken = useRef<any>(null);
|
const requestToken = useRef<any>(null);
|
||||||
const { initialize } = useOverlayScroller();
|
const { initialize } = useOverlayScroller();
|
||||||
const { initialize: innitializeParams } = useOverlayScroller();
|
const { initialize: innitializeParams } = useOverlayScroller();
|
||||||
|
const streamReaderRef = useRef<any>(null);
|
||||||
|
const requestIdRef = useRef<number>(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (scroller.current) {
|
if (scroller.current) {
|
||||||
@@ -46,6 +50,11 @@ export default function useTextImage(props: any) {
|
|||||||
}
|
}
|
||||||
}, [innitializeParams]);
|
}, [innitializeParams]);
|
||||||
|
|
||||||
|
const updateRequestId = () => {
|
||||||
|
requestIdRef.current = requestIdRef.current + 1;
|
||||||
|
return requestIdRef.current;
|
||||||
|
};
|
||||||
|
|
||||||
const removeBase64Suffix = (str: string, suffix: string) => {
|
const removeBase64Suffix = (str: string, suffix: string) => {
|
||||||
return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
|
return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
|
||||||
};
|
};
|
||||||
@@ -78,9 +87,18 @@ export default function useTextImage(props: any) {
|
|||||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const stopDebounce = _.debounce(() => {
|
||||||
|
setImageList([]);
|
||||||
|
setLoading(false);
|
||||||
|
}, 200);
|
||||||
|
|
||||||
const submitMessage = async (parameters: any) => {
|
const submitMessage = async (parameters: any) => {
|
||||||
try {
|
try {
|
||||||
if (!parameters.model) return;
|
if (!parameters.model) return;
|
||||||
|
|
||||||
|
requestToken.current?.abort?.('cancel');
|
||||||
|
requestToken.current = new AbortController();
|
||||||
|
const currentRequestId = updateRequestId();
|
||||||
const size: any = setImageSize(parameters);
|
const size: any = setImageSize(parameters);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setMessageId();
|
setMessageId();
|
||||||
@@ -107,9 +125,6 @@ export default function useTextImage(props: any) {
|
|||||||
});
|
});
|
||||||
setImageList(newImageList);
|
setImageList(newImageList);
|
||||||
|
|
||||||
requestToken.current?.abort?.('cancel');
|
|
||||||
requestToken.current = new AbortController();
|
|
||||||
|
|
||||||
let result: any = {};
|
let result: any = {};
|
||||||
if (API === CREAT_IMAGE_API) {
|
if (API === CREAT_IMAGE_API) {
|
||||||
result = await fetchChunkedData({
|
result = await fetchChunkedData({
|
||||||
@@ -135,10 +150,15 @@ export default function useTextImage(props: any) {
|
|||||||
setImageList([]);
|
setImageList([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
console.log('result:', result);
|
||||||
const { reader, decoder } = result;
|
const { reader, decoder } = result;
|
||||||
|
streamReaderRef.current = reader;
|
||||||
await readStreamData(reader, decoder, (chunk: any) => {
|
await readStreamData(reader, decoder, (chunk: any, done?: boolean) => {
|
||||||
|
console.log('chunk done:', chunk, done);
|
||||||
|
if (requestIdRef.current !== currentRequestId) {
|
||||||
|
// If the request ID has changed, ignore this chunk
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (chunk?.error) {
|
if (chunk?.error) {
|
||||||
setTokenResult({
|
setTokenResult({
|
||||||
error: true,
|
error: true,
|
||||||
@@ -168,12 +188,25 @@ export default function useTextImage(props: any) {
|
|||||||
progress: progress
|
progress: progress
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
if (
|
||||||
|
done &&
|
||||||
|
!chunk?.error &&
|
||||||
|
newImageList.some((item) => item.progress < 100)
|
||||||
|
) {
|
||||||
|
setTokenResult({
|
||||||
|
error: true,
|
||||||
|
errorMessage: intl.formatMessage({
|
||||||
|
id: 'playground.image.generate.error'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
setImageList([...newImageList]);
|
setImageList([...newImageList]);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('error:', error);
|
console.log('error:', error);
|
||||||
|
updateRequestId();
|
||||||
|
stopDebounce();
|
||||||
requestToken.current?.abort?.('cancel');
|
requestToken.current?.abort?.('cancel');
|
||||||
setImageList([]);
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -187,8 +220,6 @@ export default function useTextImage(props: any) {
|
|||||||
|
|
||||||
const handleStopConversation = () => {
|
const handleStopConversation = () => {
|
||||||
requestToken.current?.abort?.('stop');
|
requestToken.current?.abort?.('stop');
|
||||||
setImageList([]);
|
|
||||||
setLoading(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Space, Typography } from 'antd';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
|
interface AddWorkerMacOSProps {
|
||||||
|
token?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerWorkerSteps = [
|
||||||
|
'Open the quick configuration file.',
|
||||||
|
`Select the "General" option.`,
|
||||||
|
`Select "Worker" as the service role.`,
|
||||||
|
'Enter the Server URL.',
|
||||||
|
'Paste the Token.',
|
||||||
|
`Click "Restart".`
|
||||||
|
];
|
||||||
|
|
||||||
|
const AddWorkerMacOS: React.FC<AddWorkerMacOSProps> = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const labels = useMemo(
|
||||||
|
() => ({
|
||||||
|
step1: intl.formatMessage({ id: 'resources.worker.add.step1' }),
|
||||||
|
step2: intl.formatMessage({ id: 'resources.worker.add.step2' }),
|
||||||
|
step2Tips: intl.formatMessage({ id: 'resources.worker.add.step2.tips' }),
|
||||||
|
step3: intl.formatMessage({ id: 'resources.worker.add.step3' }),
|
||||||
|
linuxOrMac: intl.formatMessage({ id: 'resources.worker.linuxormaxos' })
|
||||||
|
}),
|
||||||
|
[intl]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="script-install">
|
||||||
|
<h3 className="font-size-14 font-600">1. Install GPUStack</h3>
|
||||||
|
<Typography.Paragraph type="secondary" style={{ paddingLeft: 14 }}>
|
||||||
|
<Typography.Link>Download Package</Typography.Link> and install it on
|
||||||
|
your macOS machine.
|
||||||
|
</Typography.Paragraph>
|
||||||
|
<h3 className="font-size-14 font-600">
|
||||||
|
2. <span dangerouslySetInnerHTML={{ __html: labels.step1 }}></span>
|
||||||
|
</h3>
|
||||||
|
<Typography.Paragraph style={{ paddingLeft: 14 }}>
|
||||||
|
<Typography.Text type="secondary">
|
||||||
|
Click <span className="font-600">Copy the token</span>
|
||||||
|
</Typography.Text>
|
||||||
|
</Typography.Paragraph>
|
||||||
|
<h3 className="m-t-10 font-size-14 font-600">
|
||||||
|
3. {labels.step2}{' '}
|
||||||
|
<span
|
||||||
|
className="font-size-12"
|
||||||
|
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `${labels.step2Tips}`
|
||||||
|
}}
|
||||||
|
></span>
|
||||||
|
</h3>
|
||||||
|
<Typography.Paragraph style={{ paddingLeft: 14 }}>
|
||||||
|
<Space direction="vertical">
|
||||||
|
{registerWorkerSteps.map((step, index) => (
|
||||||
|
<Typography.Text key={index} type="secondary">
|
||||||
|
{index + 1}. {step}
|
||||||
|
</Typography.Text>
|
||||||
|
))}
|
||||||
|
</Space>
|
||||||
|
</Typography.Paragraph>
|
||||||
|
<h3 className="m-b-0 m-t-10 font-size-14 font-600">4. {labels.step3}</h3>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddWorkerMacOS;
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface AddWorkerWindowsProps {
|
||||||
|
token?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddWorkerWindows: React.FC<AddWorkerWindowsProps> = () => {
|
||||||
|
return <div>add worker in windows</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddWorkerWindows;
|
||||||
@@ -23,9 +23,22 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'container',
|
key: 'container',
|
||||||
label: intl.formatMessage({ id: 'resources.worker.container.install' }),
|
label: 'Linux',
|
||||||
|
// icon: <LinuxOutlined />,
|
||||||
children: <ContainerInstall token={token} />
|
children: <ContainerInstall token={token} />
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// key: 'macos',
|
||||||
|
// label: 'macOS',
|
||||||
|
// icon: <AppleOutlined />,
|
||||||
|
// children: <MacOS token={token} />
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: 'windows',
|
||||||
|
// label: 'Windows',
|
||||||
|
// icon: <WindowsOutlined />,
|
||||||
|
// children: <Windows token={token} />
|
||||||
|
// }
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -193,7 +193,11 @@ export const readStreamData = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Process the remainder of the buffer
|
// Process the remainder of the buffer
|
||||||
const processBuffer = async (buffer: string, callback: (data: any) => void) => {
|
const processBuffer = async (
|
||||||
|
buffer: string,
|
||||||
|
callback: (data: any, done?: boolean) => void,
|
||||||
|
done?: boolean
|
||||||
|
) => {
|
||||||
if (!buffer) return;
|
if (!buffer) return;
|
||||||
|
|
||||||
const lines = buffer.split('\n');
|
const lines = buffer.split('\n');
|
||||||
@@ -205,7 +209,7 @@ const processBuffer = async (buffer: string, callback: (data: any) => void) => {
|
|||||||
try {
|
try {
|
||||||
if (jsonStr !== '[DONE]') {
|
if (jsonStr !== '[DONE]') {
|
||||||
const jsonData = JSON.parse(jsonStr);
|
const jsonData = JSON.parse(jsonStr);
|
||||||
callback(jsonData);
|
callback(jsonData, done);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to parse JSON from line:', jsonStr, e);
|
console.error('Failed to parse JSON from line:', jsonStr, e);
|
||||||
@@ -214,7 +218,7 @@ const processBuffer = async (buffer: string, callback: (data: any) => void) => {
|
|||||||
const errorStr = trimmedLine.slice(7).trim();
|
const errorStr = trimmedLine.slice(7).trim();
|
||||||
try {
|
try {
|
||||||
const jsonData = JSON.parse(errorStr);
|
const jsonData = JSON.parse(errorStr);
|
||||||
callback({ error: jsonData });
|
callback({ error: jsonData, done });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to parse error JSON from line:', errorStr, e);
|
console.error('Failed to parse error JSON from line:', errorStr, e);
|
||||||
}
|
}
|
||||||
@@ -225,7 +229,7 @@ const processBuffer = async (buffer: string, callback: (data: any) => void) => {
|
|||||||
export const readLargeStreamData = async (
|
export const readLargeStreamData = async (
|
||||||
reader: any,
|
reader: any,
|
||||||
decoder: TextDecoder,
|
decoder: TextDecoder,
|
||||||
callback: (data: any) => void,
|
callback: (data: any, done?: boolean) => void,
|
||||||
throttleDelay = 200
|
throttleDelay = 200
|
||||||
) => {
|
) => {
|
||||||
let buffer = ''; // cache incomplete line
|
let buffer = ''; // cache incomplete line
|
||||||
@@ -234,9 +238,9 @@ export const readLargeStreamData = async (
|
|||||||
private buffer: any[] = [];
|
private buffer: any[] = [];
|
||||||
private failed: boolean = false;
|
private failed: boolean = false;
|
||||||
private isFlushing: boolean = false;
|
private isFlushing: boolean = false;
|
||||||
private callback: (data: any) => void;
|
private callback: (data: any, done?: boolean) => void;
|
||||||
|
|
||||||
constructor(callback: (data: any) => void) {
|
constructor(callback: (data: any, done?: boolean) => void) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +248,12 @@ export const readLargeStreamData = async (
|
|||||||
this.buffer.push(data);
|
this.buffer.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async flush() {
|
public async flush(done?: boolean) {
|
||||||
|
if (this.buffer.length === 0 && done) {
|
||||||
|
// If buffer is empty and done is true, we can call the callback with an empty object
|
||||||
|
this.callback({}, done);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.buffer.length === 0 || this.isFlushing) {
|
if (this.buffer.length === 0 || this.isFlushing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -255,7 +264,7 @@ export const readLargeStreamData = async (
|
|||||||
const data = this.buffer.shift();
|
const data = this.buffer.shift();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
processBuffer(data, this.callback);
|
processBuffer(data, this.callback, done);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error processing buffer:', error);
|
console.error('Error processing buffer:', error);
|
||||||
this.failed = true;
|
this.failed = true;
|
||||||
@@ -263,6 +272,10 @@ export const readLargeStreamData = async (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (done) {
|
||||||
|
// If done is true, we should call the callback with an empty object
|
||||||
|
this.callback({}, done);
|
||||||
|
}
|
||||||
this.isFlushing = false;
|
this.isFlushing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,13 +295,15 @@ export const readLargeStreamData = async (
|
|||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader?.read?.();
|
const { done, value } = await reader?.read?.();
|
||||||
|
|
||||||
|
console.log('done:', done, 'value:', value);
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
isReading = false;
|
isReading = false;
|
||||||
// Process remaining buffered data
|
// Process remaining buffered data
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
bufferManager.add(buffer);
|
bufferManager.add(buffer);
|
||||||
}
|
}
|
||||||
bufferManager.flush();
|
bufferManager.flush(done);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user