feat(ui): clean up network stuff

- Remove unused dependency on `openapi-fetch`
- Organise network-related nanostores
This commit is contained in:
psychedelicious 2023-11-25 13:48:53 +11:00 committed by Kent Keirsey
parent da4aab9233
commit 785d584603
15 changed files with 74 additions and 183 deletions

View File

@ -19,7 +19,6 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"prepare": "cd ../../../ && husky install invokeai/frontend/web/.husky",
"dev": "concurrently \"vite dev\" \"yarn run theme:watch\"", "dev": "concurrently \"vite dev\" \"yarn run theme:watch\"",
"dev:host": "concurrently \"vite dev --host\" \"yarn run theme:watch\"", "dev:host": "concurrently \"vite dev --host\" \"yarn run theme:watch\"",
"build": "yarn run lint && vite build", "build": "yarn run lint && vite build",
@ -30,7 +29,7 @@
"lint:prettier": "prettier --check .", "lint:prettier": "prettier --check .",
"lint:tsc": "tsc --noEmit", "lint:tsc": "tsc --noEmit",
"lint": "concurrently -g -n eslint,prettier,tsc,madge -c cyan,green,magenta,yellow \"yarn run lint:eslint\" \"yarn run lint:prettier\" \"yarn run lint:tsc\" \"yarn run lint:madge\"", "lint": "concurrently -g -n eslint,prettier,tsc,madge -c cyan,green,magenta,yellow \"yarn run lint:eslint\" \"yarn run lint:prettier\" \"yarn run lint:tsc\" \"yarn run lint:madge\"",
"fix": "eslint --fix . && prettier --loglevel warn --write . && tsc --noEmit", "fix": "eslint --fix . && prettier --loglevel warn --write .",
"lint-staged": "lint-staged", "lint-staged": "lint-staged",
"postinstall": "patch-package && yarn run theme", "postinstall": "patch-package && yarn run theme",
"theme": "chakra-cli tokens src/theme/theme.ts", "theme": "chakra-cli tokens src/theme/theme.ts",
@ -80,7 +79,6 @@
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"nanostores": "^0.9.4", "nanostores": "^0.9.4",
"new-github-issue-url": "^1.0.0", "new-github-issue-url": "^1.0.0",
"openapi-fetch": "^0.8.1",
"overlayscrollbars": "^2.4.4", "overlayscrollbars": "^2.4.4",
"overlayscrollbars-react": "^0.5.3", "overlayscrollbars-react": "^0.5.3",
"patch-package": "^8.0.0", "patch-package": "^8.0.0",

View File

@ -1,13 +1,14 @@
import { Middleware } from '@reduxjs/toolkit'; import { Middleware } from '@reduxjs/toolkit';
import { $socketOptions } from 'app/hooks/useSocketIO';
import { $authToken } from 'app/store/nanostores/authToken';
import { $baseUrl } from 'app/store/nanostores/baseUrl';
import { $customStarUI, CustomStarUi } from 'app/store/nanostores/customStarUI'; import { $customStarUI, CustomStarUi } from 'app/store/nanostores/customStarUI';
import { $headerComponent } from 'app/store/nanostores/headerComponent'; import { $headerComponent } from 'app/store/nanostores/headerComponent';
import { $isDebugging } from 'app/store/nanostores/isDebugging'; import { $isDebugging } from 'app/store/nanostores/isDebugging';
import { $projectId } from 'app/store/nanostores/projectId';
import { $queueId, DEFAULT_QUEUE_ID } from 'app/store/nanostores/queueId';
import { store } from 'app/store/store'; import { store } from 'app/store/store';
import { PartialAppConfig } from 'app/types/invokeai'; import { PartialAppConfig } from 'app/types/invokeai';
import {
$queueId,
DEFAULT_QUEUE_ID,
} from 'features/queue/store/queueNanoStore';
import React, { import React, {
PropsWithChildren, PropsWithChildren,
ReactNode, ReactNode,
@ -16,13 +17,11 @@ import React, {
useEffect, useEffect,
} from 'react'; } from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { $authToken, $baseUrl, $projectId } from 'services/api/client'; import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
import { ManagerOptions, SocketOptions } from 'socket.io-client'; import { ManagerOptions, SocketOptions } from 'socket.io-client';
import Loading from '../../common/components/Loading/Loading'; import Loading from '../../common/components/Loading/Loading';
import AppDndContext from '../../features/dnd/components/AppDndContext'; import AppDndContext from '../../features/dnd/components/AppDndContext';
import '../../i18n'; import '../../i18n';
import { $socketOptions } from '../hooks/useSocketIO';
import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
const App = lazy(() => import('./App')); const App = lazy(() => import('./App'));
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));

View File

@ -1,9 +1,10 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { $authToken } from 'app/store/nanostores/authToken';
import { $baseUrl } from 'app/store/nanostores/baseUrl';
import { $isDebugging } from 'app/store/nanostores/isDebugging'; import { $isDebugging } from 'app/store/nanostores/isDebugging';
import { useAppDispatch } from 'app/store/storeHooks'; import { useAppDispatch } from 'app/store/storeHooks';
import { MapStore, WritableAtom, atom, map } from 'nanostores'; import { MapStore, WritableAtom, atom, map } from 'nanostores';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { $authToken, $baseUrl } from 'services/api/client';
import { import {
ClientToServerEvents, ClientToServerEvents,
ServerToClientEvents, ServerToClientEvents,
@ -11,6 +12,7 @@ import {
import { setEventListeners } from 'services/events/util/setEventListeners'; import { setEventListeners } from 'services/events/util/setEventListeners';
import { ManagerOptions, Socket, SocketOptions, io } from 'socket.io-client'; import { ManagerOptions, Socket, SocketOptions, io } from 'socket.io-client';
// Inject socket options and url into window for debugging
declare global { declare global {
interface Window { interface Window {
$socketOptions?: MapStore<Partial<ManagerOptions & SocketOptions>>; $socketOptions?: MapStore<Partial<ManagerOptions & SocketOptions>>;
@ -65,7 +67,11 @@ const makeSocket = (): Socket<ServerToClientEvents, ClientToServerEvents> => {
export const $socketOptions = map<Partial<ManagerOptions & SocketOptions>>({}); export const $socketOptions = map<Partial<ManagerOptions & SocketOptions>>({});
export const $socketUrl = atom<string>(makeSocketUrl()); export const $socketUrl = atom<string>(makeSocketUrl());
export const $isSocketInitialized = atom<boolean>(false);
/**
* Initializes the socket.io connection and sets up event listeners.
*/
export const useSocketIO = () => { export const useSocketIO = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const socketOptions = useStore($socketOptions); const socketOptions = useStore($socketOptions);
@ -74,6 +80,10 @@ export const useSocketIO = () => {
const authToken = useStore($authToken); const authToken = useStore($authToken);
useEffect(() => { useEffect(() => {
if ($isSocketInitialized.get()) {
// Singleton!
return;
}
const socket = makeSocket(); const socket = makeSocket();
setEventListeners({ dispatch, socket }); setEventListeners({ dispatch, socket });
socket.connect(); socket.connect();
@ -84,6 +94,8 @@ export const useSocketIO = () => {
console.log('Socket initialized', socket); console.log('Socket initialized', socket);
} }
$isSocketInitialized.set(true);
return () => { return () => {
if ($isDebugging.get()) { if ($isDebugging.get()) {
window.$socketOptions = undefined; window.$socketOptions = undefined;
@ -91,6 +103,7 @@ export const useSocketIO = () => {
console.log('Socket teardown', socket); console.log('Socket teardown', socket);
} }
socket.disconnect(); socket.disconnect();
$isSocketInitialized.set(false);
}; };
}, [dispatch, socketOptions, socketUrl, baseUrl, authToken]); }, [dispatch, socketOptions, socketUrl, baseUrl, authToken]);
}; };

View File

@ -0,0 +1,6 @@
import { atom } from 'nanostores';
/**
* The user's auth token.
*/
export const $authToken = atom<string | undefined>();

View File

@ -0,0 +1,6 @@
import { atom } from 'nanostores';
/**
* The OpenAPI base url.
*/
export const $baseUrl = atom<string | undefined>();

View File

@ -0,0 +1,6 @@
import { atom } from 'nanostores';
/**
* The optional project-id header.
*/
export const $projectId = atom<string | undefined>();

View File

@ -1,5 +1,5 @@
import { $authToken } from 'app/store/nanostores/authToken';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { $authToken } from 'services/api/client';
/** /**
* Converts an image URL to a Blob by creating an <img /> element, drawing it to canvas * Converts an image URL to a Blob by creating an <img /> element, drawing it to canvas

View File

@ -1,7 +1,7 @@
import { skipToken } from '@reduxjs/toolkit/dist/query'; import { skipToken } from '@reduxjs/toolkit/dist/query';
import { $authToken } from 'app/store/nanostores/authToken';
import { memo } from 'react'; import { memo } from 'react';
import { Image } from 'react-konva'; import { Image } from 'react-konva';
import { $authToken } from 'services/api/client';
import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import useImage from 'use-image'; import useImage from 'use-image';
import { CanvasImage } from '../store/canvasTypes'; import { CanvasImage } from '../store/canvasTypes';

View File

@ -1,43 +0,0 @@
import { atom, computed } from 'nanostores';
import createClient from 'openapi-fetch';
import { paths } from 'services/api/schema';
/**
* We use nanostores to store the token and base url for very simple reactivity
*/
/**
* The user's auth token.
*/
export const $authToken = atom<string | undefined>();
/**
* The OpenAPI base url.
*/
export const $baseUrl = atom<string | undefined>();
/**
* The optional project-id header.
*/
export const $projectId = atom<string | undefined>();
/**
* Autogenerated, type-safe fetch client for the API. Used when RTK Query is not an option.
* Dynamically updates when the token or base url changes.
* Use `$client.get()` to get the client.
*
* @example
* const { get, post, del } = $client.get();
*/
export const $client = computed(
[$authToken, $baseUrl, $projectId],
(authToken, baseUrl, projectId) =>
createClient<paths>({
headers: {
...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
...(projectId ? { 'project-id': projectId } : {}),
},
// do not include `api/v1` in the base url for this client
baseUrl: `${baseUrl ?? ''}`,
})
);

View File

@ -4,7 +4,7 @@ import {
ThunkDispatch, ThunkDispatch,
createEntityAdapter, createEntityAdapter,
} from '@reduxjs/toolkit'; } from '@reduxjs/toolkit';
import { $queueId } from 'features/queue/store/queueNanoStore'; import { $queueId } from 'app/store/nanostores/queueId';
import { listParamsReset } from 'features/queue/store/queueSlice'; import { listParamsReset } from 'features/queue/store/queueSlice';
import queryString from 'query-string'; import queryString from 'query-string';
import { ApiTagDescription, api } from '..'; import { ApiTagDescription, api } from '..';

View File

@ -6,7 +6,9 @@ import {
createApi, createApi,
fetchBaseQuery, fetchBaseQuery,
} from '@reduxjs/toolkit/query/react'; } from '@reduxjs/toolkit/query/react';
import { $authToken, $baseUrl, $projectId } from 'services/api/client'; import { $authToken } from 'app/store/nanostores/authToken';
import { $baseUrl } from 'app/store/nanostores/baseUrl';
import { $projectId } from 'app/store/nanostores/projectId';
export const tagTypes = [ export const tagTypes = [
'AppVersion', 'AppVersion',

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
import { $queueId } from 'app/store/nanostores/queueId';
import { AppDispatch } from 'app/store/store'; import { AppDispatch } from 'app/store/store';
import { $queueId } from 'features/queue/store/queueNanoStore';
import { addToast } from 'features/system/store/systemSlice'; import { addToast } from 'features/system/store/systemSlice';
import { makeToast } from 'features/system/util/makeToast'; import { makeToast } from 'features/system/util/makeToast';
import { Socket } from 'socket.io-client'; import { Socket } from 'socket.io-client';

View File

@ -5028,23 +5028,11 @@ open@^8.4.0:
is-docker "^2.1.1" is-docker "^2.1.1"
is-wsl "^2.2.0" is-wsl "^2.2.0"
openapi-fetch@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.8.1.tgz#a2bda1f72a8311e92cc789d1c8fec7b2d8ca28b6"
integrity sha512-xmzMaBCydPTMd0TKy4P2DYx/JOe9yjXtPIky1n1GV7nJJdZ3IZgSHvAWVbe06WsPD8EreR7E97IAiskPr6sa2g==
dependencies:
openapi-typescript-helpers "^0.0.4"
openapi-types@^12.1.3: openapi-types@^12.1.3:
version "12.1.3" version "12.1.3"
resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3"
integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==
openapi-typescript-helpers@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.4.tgz#ffe7c4868f094fcc8502dbdcddc6c32ce8011aee"
integrity sha512-Q0MTapapFAG993+dx8lNw33X6P/6EbFr31yNymJHq56fNc6dODyRm8tWyRnGxuC74lyl1iCRMV6nQCGQsfVNKg==
openapi-typescript@^6.7.0: openapi-typescript@^6.7.0:
version "6.7.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/openapi-typescript/-/openapi-typescript-6.7.0.tgz#6d1a4dfc0db60b61573a3ea3c52984a79c638c67" resolved "https://registry.yarnpkg.com/openapi-typescript/-/openapi-typescript-6.7.0.tgz#6d1a4dfc0db60b61573a3ea3c52984a79c638c67"