Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend prep for migration to nodes #2451

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions invokeai/frontend/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"plugins": [
[
"transform-imports",
{
"lodash": {
"transform": "lodash/${member}",
"preventFullImport": true
}
}
]
]
}
6 changes: 6 additions & 0 deletions invokeai/frontend/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/
.husky/
node_modules/
patches/
public/
src/services/
13 changes: 0 additions & 13 deletions invokeai/frontend/.eslintrc.cjs

This file was deleted.

40 changes: 40 additions & 0 deletions invokeai/frontend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module.exports = {
env: {
browser: true,
es6: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:prettier/recommended',
'plugin:react/jsx-runtime',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['react', '@typescript-eslint', 'eslint-plugin-react-hooks'],
root: true,
rules: {
'react-hooks/exhaustive-deps': 'error',
'no-var': 'error',
'brace-style': 'error',
'prefer-template': 'error',
radix: 'error',
'space-before-blocks': 'error',
'import/prefer-default-export': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { varsIgnorePattern: '_+' }],
},
settings: {
react: {
version: 'detect',
},
},
};
3 changes: 3 additions & 0 deletions invokeai/frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# build stats
stats.html
4 changes: 4 additions & 0 deletions invokeai/frontend/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

cd invokeai/frontend/ && yarn run lint
6 changes: 6 additions & 0 deletions invokeai/frontend/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/
.husky/
node_modules/
patches/
public/
src/services/
6 changes: 6 additions & 0 deletions invokeai/frontend/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
trailingComma: 'es5',
tabWidth: 2,
semi: true,
singleQuote: true,
};
48 changes: 0 additions & 48 deletions invokeai/frontend/dist/assets/index-legacy-8f3bb5f8.js

This file was deleted.

40 changes: 40 additions & 0 deletions invokeai/frontend/dist/assets/index-legacy-b2c8bd7e.js

Large diffs are not rendered by default.

625 changes: 0 additions & 625 deletions invokeai/frontend/dist/assets/index.2a9ecaa6.js

This file was deleted.

599 changes: 599 additions & 0 deletions invokeai/frontend/dist/assets/index.6ac48a47.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions invokeai/frontend/dist/assets/index.7c62aab5.css

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion invokeai/frontend/dist/assets/index.8badc8b4.css

This file was deleted.

4 changes: 4 additions & 0 deletions invokeai/frontend/dist/assets/polyfills-legacy-95446b53.js

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions invokeai/frontend/dist/assets/polyfills-legacy-dde3a68a.js

This file was deleted.

8 changes: 4 additions & 4 deletions invokeai/frontend/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>InvokeAI - A Stable Diffusion Toolkit</title>
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
<script type="module" crossorigin src="./assets/index.2a9ecaa6.js"></script>
<link rel="stylesheet" href="./assets/index.8badc8b4.css">
<script type="module" crossorigin src="./assets/index.6ac48a47.js"></script>
<link rel="stylesheet" href="./assets/index.7c62aab5.css">
<script type="module">try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.__vite_is_modern_browser=true;</script>
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
</head>
Expand All @@ -17,7 +17,7 @@
<div id="root"></div>

<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-dde3a68a.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-8f3bb5f8.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-95446b53.js"></script>
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-b2c8bd7e.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>
34 changes: 26 additions & 8 deletions invokeai/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
"name": "invoke-ai-ui",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "tsc && vite build",
"build-dev": "tsc && vite build -m development",
"prepare": "cd ../../ && husky install invokeai/frontend/.husky",
"dev": "yarn run gen-api && vite dev",
"build": "tsc && yarn run gen-api && vite build",
"build-dev": "tsc && yarn run gen-api && vite build -m development",
"preview": "vite preview",
"madge": "madge --circular src/main.tsx",
"lint": "eslint src/",
"prettier": "prettier *.{json,cjs,ts,html} src/**/*.{ts,tsx}",
"lint": "eslint --fix .",
"lint-staged": "lint-staged",
"prettier": "prettier *.{json,js,ts,html} src/**/*.{ts,tsx,scss} --write .",
"fmt": "npm run prettier -- --write",
"postinstall": "patch-package"
"postinstall": "patch-package",
"gen-api": "openapi -i http://127.0.0.1:9090/openapi.json -o src/services/openapi"
},
"dependencies": {
"@chakra-ui/icons": "^2.0.10",
Expand Down Expand Up @@ -64,15 +66,25 @@
"@typescript-eslint/parser": "^5.36.2",
"@vitejs/plugin-legacy": "^3.0.1",
"@vitejs/plugin-react": "^2.0.1",
"babel-plugin-transform-imports": "^2.0.0",
"eslint": "^8.23.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"lint-staged": "^13.1.0",
"madge": "^5.0.1",
"openapi-typescript": "^6.1.0",
"openapi-typescript-codegen": "^0.23.0",
"patch-package": "^6.5.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.1",
"prettier": "^2.8.3",
"prettier-plugin-organize-imports": "^3.2.2",
"rollup-plugin-visualizer": "^5.9.0",
"sass": "^1.55.0",
"terser": "^5.16.1",
"ts-node": "^10.9.1",
"tsc-watch": "^5.0.3",
"typescript": "^4.6.4",
"vite": "^3.0.7",
Expand All @@ -88,5 +100,11 @@
"skipTypeImports": true
}
}
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx,cjs}": [
"npx prettier --write",
"npx eslint --fix"
]
}
}
111 changes: 105 additions & 6 deletions invokeai/frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,123 @@
import ImageUploader from 'common/components/ImageUploader';
import Console from 'features/system/components/Console';
import ProgressBar from 'features/system/components/ProgressBar';
import SiteHeader from 'features/system/components/SiteHeader';
import Console from 'features/system/components/Console';
import InvokeTabs from 'features/ui/components/InvokeTabs';
import { keepGUIAlive } from './utils';
import InvokeTabs from 'features/tabs/components/InvokeTabs';
import ImageUploader from 'common/components/ImageUploader';

import { Button, Flex, Text } from '@chakra-ui/react';
import { SessionsService } from 'services/openapi';

import useToastWatcher from 'features/system/hooks/useToastWatcher';

import FloatingOptionsPanelButtons from 'features/tabs/components/FloatingOptionsPanelButtons';
import FloatingGalleryButton from 'features/tabs/components/FloatingGalleryButton';
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
import { useEffect, useState } from 'react';
import { io } from 'socket.io-client';

type GeneratorProgress = {
session_id: string;
invocation_id: string;
step: number;
percent: number;
};

keepGUIAlive();

const socket_url = `ws://${window.location.host}`;
const socket = io(socket_url, {
path: '/ws/socket.io',
});

const App = () => {
useToastWatcher();

const [sessionId, setSessionId] = useState<string>();
const [invocationProgress, setInvocationProgress] = useState<number>();
const [isInvocationPending, setIsInvocationPending] = useState(false);

const handleCreateSession = async () => {
const { id } = await SessionsService.createSession({
nodes: [
{
id: 'a',
type: 'txt2img',
prompt: 'pizza',
steps: 10,
},
{
id: 'b',
type: 'show_image',
},
],
links: [
{
from_node: { id: 'a', field: 'image' },
to_node: { id: 'b', field: 'image' },
},
],
});

setSessionId(id);
socket.emit('subscribe', { session: id });
};

const handleInvokeSession = async () => {
if (sessionId) {
setIsInvocationPending(true);
SessionsService.invokeSession(sessionId, true);
}
};

useEffect(() => {
socket.removeAllListeners();
socket.on('generator_progress', (data: GeneratorProgress) => {
console.log('generator_progress', data);
setInvocationProgress(data.percent);
});
socket.on('invocation_complete', async (data) => {
setIsInvocationPending(false);
setInvocationProgress(undefined);
setSessionId(undefined);
console.log('invocation_complete', data);
socket.emit('unsubscribe', { session: sessionId });
});
socket.on('invocation_started', (data) =>
console.log('invocation_started', data)
);
socket.on('session_complete', (data) => {
console.log('session_complete', data);
});

() => {
socket.emit('unsubscribe', { session: sessionId });
socket.removeAllListeners();
socket.disconnect();
};
}, [sessionId]);

return (
<div className="App">
<ImageUploader>
<ProgressBar />
<Flex gap={2} p={2} alignItems="center">
<Button onClick={handleCreateSession} isDisabled={!!sessionId}>
Create Session
</Button>
<Button
onClick={handleInvokeSession}
isDisabled={!sessionId || isInvocationPending}
isLoading={isInvocationPending}
loadingText={`Invoking ${
invocationProgress === undefined
? '...'
: `${Math.round(invocationProgress * 100)}%`
}`}
>
Invoke
</Button>
{sessionId && <Text>Session: {sessionId}</Text>}
</Flex>
<div className="app-content">
<SiteHeader />
<InvokeTabs />
Expand All @@ -27,7 +126,7 @@ const App = () => {
<Console />
</div>
</ImageUploader>
<FloatingOptionsPanelButtons />
<FloatingParametersPanelButtons />
<FloatingGalleryButton />
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion invokeai/frontend/src/app/invokeai.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* 'gfpgan'.
*/

import { InvokeTabName } from 'features/tabs/tabMap';
import { InvokeTabName } from 'features/ui/store/tabMap';
import { IRect } from 'konva/lib/types';

/**
Expand Down
26 changes: 10 additions & 16 deletions invokeai/frontend/src/app/selectors/readinessSelector.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
import { createSelector } from '@reduxjs/toolkit';
import _ from 'lodash';
import { RootState } from 'app/store';
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
import { OptionsState } from 'features/options/store/optionsSlice';
import { SystemState } from 'features/system/store/systemSlice';
import { validateSeedWeights } from 'common/util/seedWeightPairs';
import { initialCanvasImageSelector } from 'features/canvas/store/canvasSelectors';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { systemSelector } from 'features/system/store/systemSelectors';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { isEqual } from 'lodash';

export const readinessSelector = createSelector(
[
(state: RootState) => state.options,
(state: RootState) => state.system,
generationSelector,
systemSelector,
initialCanvasImageSelector,
activeTabNameSelector,
],
(
options: OptionsState,
system: SystemState,
initialCanvasImage,
activeTabName
) => {
(generation, system, initialCanvasImage, activeTabName) => {
const {
prompt,
shouldGenerateVariations,
seedWeights,
initialImage,
seed,
} = options;
} = generation;

const { isProcessing, isConnected } = system;

Expand Down Expand Up @@ -71,8 +65,8 @@ export const readinessSelector = createSelector(
},
{
memoizeOptions: {
equalityCheck: _.isEqual,
resultEqualityCheck: _.isEqual,
equalityCheck: isEqual,
resultEqualityCheck: isEqual,
},
}
);
4 changes: 2 additions & 2 deletions invokeai/frontend/src/app/socketio/actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createAction } from '@reduxjs/toolkit';
import { GalleryCategory } from 'features/gallery/store/gallerySlice';
import { InvokeTabName } from 'features/tabs/tabMap';
import * as InvokeAI from 'app/invokeai';
import { GalleryCategory } from 'features/gallery/store/gallerySlice';
import { InvokeTabName } from 'features/ui/store/tabMap';

/**
* We can't use redux-toolkit's createSlice() to make these actions,
Expand Down
Loading