From 22a0b3be4573361cc0af4881b5a2f2e178d910d1 Mon Sep 17 00:00:00 2001 From: caranicas Date: Sat, 24 Sep 2022 13:47:30 -0400 Subject: [PATCH] workable plan --- .../build_src/src/api/hooks/asyncGenerator.ts | 28 -- .../build_src/src/api/hooks/callbackQuery.ts | 21 -- .../build_src/src/api/hooks/eventSource.ts | 19 -- .../src/api/hooks/infiniteEventSource.ts | 47 --- ui/frontend/build_src/src/api/index.ts | 6 +- .../makeButton}/audioDing/index.tsx | 2 +- .../basicCreation/makeButton/index.tsx | 161 ++++++---- .../organisms/displayPanel/index.tsx | 291 +++++++++++------- .../build_src/src/stores/imageCreateStore.ts | 4 +- .../src/stores/imageFetchingStore.ts | 71 +++++ ui/sd_internal/runtime.py | 8 +- 11 files changed, 370 insertions(+), 288 deletions(-) delete mode 100644 ui/frontend/build_src/src/api/hooks/asyncGenerator.ts delete mode 100644 ui/frontend/build_src/src/api/hooks/callbackQuery.ts delete mode 100644 ui/frontend/build_src/src/api/hooks/eventSource.ts delete mode 100644 ui/frontend/build_src/src/api/hooks/infiniteEventSource.ts rename ui/frontend/build_src/src/components/organisms/{displayPanel => creationPanel/basicCreation/makeButton}/audioDing/index.tsx (86%) create mode 100644 ui/frontend/build_src/src/stores/imageFetchingStore.ts diff --git a/ui/frontend/build_src/src/api/hooks/asyncGenerator.ts b/ui/frontend/build_src/src/api/hooks/asyncGenerator.ts deleted file mode 100644 index 8de487d2..00000000 --- a/ui/frontend/build_src/src/api/hooks/asyncGenerator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { useInfiniteQuery } from "@tanstack/react-query"; - -export const useAyncGeneratorQuery = (key: string, asyncGeneratorFn: () => Generator) => { - - const queryFn = React.useCallback((_: any, params: CustomQueryParams) => { - if (!params) { return Promise.resolve([]) } - return Promise.resolve(params.eventData); - }, []) - - const { data, fetchMore } = useInfiniteQuery(key, queryFn as any, { getFetchMore: () => ({ eventData: [] }) }) - - const customStatus = React.useRef('success'); - - React.useEffect(() => { - (async function doReceive() { - try { - for await (let data of asyncGeneratorFn()) { - fetchMore({ eventData: data }); - } - } catch (e) { - customStatus.current = 'error'; - } - })(); - - }, [asyncGeneratorFn, fetchMore]) - - return { status: customStatus.current, data }; -} \ No newline at end of file diff --git a/ui/frontend/build_src/src/api/hooks/callbackQuery.ts b/ui/frontend/build_src/src/api/hooks/callbackQuery.ts deleted file mode 100644 index 61fc3696..00000000 --- a/ui/frontend/build_src/src/api/hooks/callbackQuery.ts +++ /dev/null @@ -1,21 +0,0 @@ -type CallbackType = (data: string[]) => void; - -type InitCallbackType = (cb: CallbackType) => void; - -export const useCallbackQuery = (key: string, initCallbackQuery: InitCallbackType) => { - - const queryFn = React.useCallback((_: any, params: CustomQueryParams) => { - if (!params) { return Promise.resolve([]) } - return Promise.resolve(params.eventData); - }, []) - - const { data, fetchMore } = useInfiniteQuery(key, queryFn as any, { getFetchMore: () => ({ eventData: [] }) }) - - const callback = React.useCallback((data) => { fetchMore({ eventData: data }) }, [fetchMore]); - - React.useEffect(() => { initCallbackQuery(callback); }, [callback, initCallbackQuery]) - - const customStatus = React.useRef('success'); - - return { status: customStatus.current, data }; -} \ No newline at end of file diff --git a/ui/frontend/build_src/src/api/hooks/eventSource.ts b/ui/frontend/build_src/src/api/hooks/eventSource.ts deleted file mode 100644 index 510272dc..00000000 --- a/ui/frontend/build_src/src/api/hooks/eventSource.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { useQuery, useQueryClient } from 'react-query' - -export const useEventSourceQuery = (queryKey, url, eventName) => { - const queryClient = useQueryClient() - - const fetchData = () => { - const evtSource = new EventSource(url) - - evtSource.addEventListener(eventName, (event) => { - const eventData = event.data && JSON.parse(event.data) - - if (eventData) { - queryClient.setQueryData(queryKey, eventData) - } - }) - } - - return useQuery(queryKey, fetchData) -} \ No newline at end of file diff --git a/ui/frontend/build_src/src/api/hooks/infiniteEventSource.ts b/ui/frontend/build_src/src/api/hooks/infiniteEventSource.ts deleted file mode 100644 index bea8a59b..00000000 --- a/ui/frontend/build_src/src/api/hooks/infiniteEventSource.ts +++ /dev/null @@ -1,47 +0,0 @@ - -import * as React from 'react'; -import { useInfiniteQuery } from 'react-query'; - -interface CustomQueryParams { - eventData: string[]; -} - -type Status = "success" | "loading" | "error"; - -export const useEventSourceQuery = (key: string, url: string, eventName: string) => { - - const eventSource = React.useRef(new EventSource(url)); - - const queryFn = React.useCallback((_: any, params: CustomQueryParams) => { - if (!params) { return Promise.resolve([]) } - return Promise.resolve(params.eventData); - }, []) - - const { data, fetchMore } = useInfiniteQuery(key, queryFn as any, { getFetchMore: () => ({ eventData: [] }) }) - - const customStatus = React.useRef('success'); - - React.useEffect(() => { - const evtSource = eventSource.current; - - const onEvent = function (ev: MessageEvent | Event) { - if (!e.data) { - return; - } - // Let's assume here we receive multiple data, ie. e.data is an array. - fetchMore({ eventData: e.data }); - } - const onError = () => { customStatus.current = 'error' }; - - evtSource.addEventListener(eventName, onEvent); - evtSource.addEventListener('error', onError); - - return () => { - evtSource.removeEventListener(eventName, onEvent); - evtSource.removeEventListener('error', onError); - } - - }, [url, eventName, fetchMore]) - - return { status: customStatus.current, data }; -} \ No newline at end of file diff --git a/ui/frontend/build_src/src/api/index.ts b/ui/frontend/build_src/src/api/index.ts index 17289282..2272c23f 100644 --- a/ui/frontend/build_src/src/api/index.ts +++ b/ui/frontend/build_src/src/api/index.ts @@ -79,7 +79,9 @@ export const doMakeImage = async (reqBody: ImageRequest) => { }, body: JSON.stringify(reqBody), }); + console.log('doMakeImage= GOT RESPONSE', res); - const data = await res.json(); - return data; + // const data = await res.json(); + // return data; + return res; }; diff --git a/ui/frontend/build_src/src/components/organisms/displayPanel/audioDing/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/audioDing/index.tsx similarity index 86% rename from ui/frontend/build_src/src/components/organisms/displayPanel/audioDing/index.tsx rename to ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/audioDing/index.tsx index 0d17816f..2a5423c5 100644 --- a/ui/frontend/build_src/src/components/organisms/displayPanel/audioDing/index.tsx +++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/audioDing/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { API_URL } from "../../../../api"; +import { API_URL } from "../../../../../../api"; const url = `${API_URL}/ding.mp3`; diff --git a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/index.tsx b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/index.tsx index 90da7659..db35aea5 100644 --- a/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/index.tsx +++ b/ui/frontend/build_src/src/components/organisms/creationPanel/basicCreation/makeButton/index.tsx @@ -1,49 +1,108 @@ +/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ +/* eslint-disable @typescript-eslint/prefer-ts-expect-error */ /* eslint-disable @typescript-eslint/naming-convention */ -import React from "react"; +import React, { useEffect } from "react"; import { useImageCreate, ImageRequest } from "../../../../../stores/imageCreateStore"; import { useImageQueue } from "../../../../../stores/imageQueueStore"; +import { + FetchingStates, + useImageFetching +} from "../../../../../stores/imageFetchingStore"; + import { v4 as uuidv4 } from "uuid"; import { useRandomSeed } from "../../../../../utils"; - +import { doMakeImage } from "../../../../../api"; import { MakeButtonStyle, // @ts-expect-error } from "./makeButton.css.ts"; import { useTranslation } from "react-i18next"; +import AudioDing from "./audioDing"; +import { parse } from "node:path/win32"; + export default function MakeButton() { const { t } = useTranslation(); const parallelCount = useImageCreate((state) => state.parallelCount); const builtRequest = useImageCreate((state) => state.builtRequest); - const addNewImage = useImageQueue((state) => state.addNewImage); - const hasQueue = useImageQueue((state) => state.hasQueuedImages()); const isRandomSeed = useImageCreate((state) => state.isRandomSeed()); const setRequestOption = useImageCreate((state) => state.setRequestOptions); - // const makeImages = () => { - // // potentially update the seed - // if (isRandomSeed) { - // // update the seed for the next time we click the button - // setRequestOption("seed", useRandomSeed()); - // } + const addNewImage = useImageQueue((state) => state.addNewImage); + const hasQueue = useImageQueue((state) => state.hasQueuedImages()); + const { id, options } = useImageQueue((state) => state.firstInQueue()); - // // the request that we have built - // const req = builtRequest(); + const setStatus = useImageFetching((state) => state.setStatus); + const appendData = useImageFetching((state) => state.appendData); - // }; + const parseRequest = async (reader: ReadableStreamDefaultReader) => { + const decoder = new TextDecoder(); + while (true) { + const { done, value } = await reader.read(); - const queueImageRequest = (req: ImageRequest) => { + if (done as boolean) { + console.log("DONE"); + setStatus(FetchingStates.COMPLETE); + break; + } + const jsonStr = decoder.decode(value); + + try { + const update = JSON.parse(jsonStr); + + if (update.status === "progress") { + console.log("PROGRESS"); + setStatus(FetchingStates.PROGRESSING); + } + else if (update.status === "succeeded") { + console.log("succeeded"); + setStatus(FetchingStates.SUCCEEDED); + // appendData(update.data); + } + else { + console.log("extra?", update); + // appendData(update.data); + } + } + catch (e) { + console.log('PARSE ERRROR') + console.log(e) + debugger; + // appendData(update.data); + } + + } + } + + const startStream = async (req: ImageRequest) => { + + const streamReq = { + ...req, + // stream_image_progress: false, + }; + + console.log("testStream", streamReq); + try { + const res = await doMakeImage(streamReq); + // @ts-expect-error + const reader = res.body.getReader(); + void parseRequest(reader); + + } catch (e) { + console.log('e'); + } + + } + + const queueImageRequest = async (req: ImageRequest) => { // the actual number of request we will make const requests = []; // the number of images we will make let { num_outputs } = req; - - // if making fewer images than the parallel count - // then it is only 1 request if (parallelCount > num_outputs) { requests.push(num_outputs); } else { @@ -63,7 +122,6 @@ export default function MakeButton() { } } - // make the requests requests.forEach((num, index) => { // get the seed we want to use let seed = req.seed; @@ -82,63 +140,42 @@ export default function MakeButton() { }); } - const testStream = async (req: ImageRequest) => { - - const streamReq = { - ...req, - stream_progress_updates: true, - // stream_image_progress: false, - session_id: uuidv4(), - }; - - console.log("testStream", streamReq); - try { - const res = await fetch('http://localhost:9000/image', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(streamReq) - }); - - console.log('res', res); - const reader = res.body.getReader(); - const decoder = new TextDecoder(); - while (true) { - const { done, value } = await reader.read(); - if (done) { - break; - } - const text = decoder.decode(value); - console.log(text); - } - } catch (e) { - console.log(e); - debugger; - } - - } - - const makeImages = () => { + const makeImageQueue = async () => { // potentially update the seed if (isRandomSeed) { // update the seed for the next time we click the button setRequestOption("seed", useRandomSeed()); } - // the request that we have built const req = builtRequest(); - - //queueImageRequest(req); - void testStream(req); - + await queueImageRequest(req); + // void startStream(req); }; + useEffect(() => { + + const makeImages = async (options: ImageRequest) => { + // potentially update the seed + await startStream(options); + } + + if (hasQueue) { + makeImages(options).catch((e) => { + console.log('HAS QUEUE ERROR'); + console.log(e); + }); + } + + + }, [hasQueue, id, options, startStream]); return (