mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): upgrade redux and RTK
There are a few breaking changes, which I've addressed. The vast majority of changes are related to new handling of `reselect`'s `createSelector` options. For better or worse, we memoize just about all our selectors using lodash `isEqual` for `resultEqualityCheck`. The upgrade requires we explicitly set the `memoize` option to `lruMemoize` to continue using lodash here. Doing that required changing our `defaultSelectorOptions`. Instead of changing that and finding dozens of instances where we weren't using that and instead were defining selector options manually, I've created a pre-configured selector: `createMemoizedSelector`. This is now used everywhere instead of `createSelector`.
This commit is contained in:
parent
99f14b1dfe
commit
72cb8b83fe
@ -65,7 +65,7 @@
|
||||
"@mantine/form": "^6.0.19",
|
||||
"@mantine/hooks": "^6.0.19",
|
||||
"@nanostores/react": "^0.7.1",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"@reduxjs/toolkit": "^2.0.1",
|
||||
"@roarr/browser-log-writer": "^1.3.0",
|
||||
"@storybook/manager-api": "^7.6.4",
|
||||
"@storybook/theming": "^7.6.4",
|
||||
@ -92,7 +92,7 @@
|
||||
"react-i18next": "^13.5.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-konva": "^18.2.10",
|
||||
"react-redux": "^8.1.3",
|
||||
"react-redux": "^9.0.2",
|
||||
"react-resizable-panels": "^0.0.55",
|
||||
"react-use": "^17.4.2",
|
||||
"react-virtuoso": "^4.6.2",
|
||||
@ -130,7 +130,6 @@
|
||||
"@types/node": "^20.9.0",
|
||||
"@types/react": "^18.2.37",
|
||||
"@types/react-dom": "^18.2.17",
|
||||
"@types/react-redux": "^7.1.32",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
||||
"@typescript-eslint/parser": "^6.13.2",
|
||||
|
@ -57,8 +57,8 @@ dependencies:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1(nanostores@0.9.5)(react@18.2.0)
|
||||
'@reduxjs/toolkit':
|
||||
specifier: ^1.9.7
|
||||
version: 1.9.7(react-redux@8.1.3)(react@18.2.0)
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1(react-redux@9.0.2)(react@18.2.0)
|
||||
'@roarr/browser-log-writer':
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
@ -138,8 +138,8 @@ dependencies:
|
||||
specifier: ^18.2.10
|
||||
version: 18.2.10(konva@9.2.3)(react-dom@18.2.0)(react@18.2.0)
|
||||
react-redux:
|
||||
specifier: ^8.1.3
|
||||
version: 8.1.3(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1)
|
||||
specifier: ^9.0.2
|
||||
version: 9.0.2(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@5.0.0)
|
||||
react-resizable-panels:
|
||||
specifier: ^0.0.55
|
||||
version: 0.0.55(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -157,7 +157,7 @@ dependencies:
|
||||
version: 2.2.0
|
||||
redux-remember:
|
||||
specifier: ^4.2.2
|
||||
version: 4.2.2(redux@4.2.1)
|
||||
version: 4.2.2(redux@5.0.0)
|
||||
roarr:
|
||||
specifier: ^7.21.0
|
||||
version: 7.21.0
|
||||
@ -226,9 +226,6 @@ devDependencies:
|
||||
'@types/react-dom':
|
||||
specifier: ^18.2.17
|
||||
version: 18.2.17
|
||||
'@types/react-redux':
|
||||
specifier: ^7.1.32
|
||||
version: 7.1.32
|
||||
'@types/uuid':
|
||||
specifier: ^9.0.7
|
||||
version: 9.0.7
|
||||
@ -4493,23 +4490,23 @@ packages:
|
||||
- immer
|
||||
dev: false
|
||||
|
||||
/@reduxjs/toolkit@1.9.7(react-redux@8.1.3)(react@18.2.0):
|
||||
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==}
|
||||
/@reduxjs/toolkit@2.0.1(react-redux@9.0.2)(react@18.2.0):
|
||||
resolution: {integrity: sha512-fxIjrR9934cmS8YXIGd9e7s1XRsEU++aFc9DVNMFMRTM5Vtsg2DCRMj21eslGtDt43IUf9bJL3h5bwUlZleibA==}
|
||||
peerDependencies:
|
||||
react: ^16.9.0 || ^17.0.0 || ^18
|
||||
react-redux: ^7.2.1 || ^8.0.2
|
||||
react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
react-redux:
|
||||
optional: true
|
||||
dependencies:
|
||||
immer: 9.0.21
|
||||
immer: 10.0.3
|
||||
react: 18.2.0
|
||||
react-redux: 8.1.3(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1)
|
||||
redux: 4.2.1
|
||||
redux-thunk: 2.4.2(redux@4.2.1)
|
||||
reselect: 4.1.8
|
||||
react-redux: 9.0.2(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@5.0.0)
|
||||
redux: 5.0.0
|
||||
redux-thunk: 3.1.0(redux@5.0.0)
|
||||
reselect: 5.0.1
|
||||
dev: false
|
||||
|
||||
/@roarr/browser-log-writer@1.3.0:
|
||||
@ -5802,12 +5799,6 @@ packages:
|
||||
'@types/node': 20.10.4
|
||||
dev: true
|
||||
|
||||
/@types/hoist-non-react-statics@3.3.1:
|
||||
resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==}
|
||||
dependencies:
|
||||
'@types/react': 18.2.42
|
||||
hoist-non-react-statics: 3.3.2
|
||||
|
||||
/@types/http-errors@2.0.4:
|
||||
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
|
||||
|
||||
@ -5922,15 +5913,6 @@ packages:
|
||||
'@types/react': 18.2.42
|
||||
dev: false
|
||||
|
||||
/@types/react-redux@7.1.32:
|
||||
resolution: {integrity: sha512-YJYV0M27cyHHJIacaRsZRx5OETzK8KWjEGnix7UH3ngItYo4It0MUBzU6WNwqnwhbrPw5wx9KXluuoTZ85Gg7A==}
|
||||
dependencies:
|
||||
'@types/hoist-non-react-statics': 3.3.1
|
||||
'@types/react': 18.2.42
|
||||
hoist-non-react-statics: 3.3.2
|
||||
redux: 4.2.1
|
||||
dev: true
|
||||
|
||||
/@types/react@18.2.42:
|
||||
resolution: {integrity: sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA==}
|
||||
dependencies:
|
||||
@ -8959,6 +8941,7 @@ packages:
|
||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||
dependencies:
|
||||
react-is: 16.13.1
|
||||
dev: false
|
||||
|
||||
/hosted-git-info@2.8.9:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
@ -9049,8 +9032,8 @@ packages:
|
||||
engines: {node: '>= 4'}
|
||||
dev: true
|
||||
|
||||
/immer@9.0.21:
|
||||
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
|
||||
/immer@10.0.3:
|
||||
resolution: {integrity: sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==}
|
||||
dev: false
|
||||
|
||||
/import-fresh@3.3.0:
|
||||
@ -11029,6 +11012,7 @@ packages:
|
||||
|
||||
/react-is@18.2.0:
|
||||
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
|
||||
dev: true
|
||||
|
||||
/react-konva@18.2.10(konva@9.2.3)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==}
|
||||
@ -11057,15 +11041,15 @@ packages:
|
||||
scheduler: 0.23.0
|
||||
dev: false
|
||||
|
||||
/react-redux@8.1.3(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1):
|
||||
resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==}
|
||||
/react-redux@9.0.2(@types/react-dom@18.2.17)(@types/react@18.2.42)(react-dom@18.2.0)(react@18.2.0)(redux@5.0.0):
|
||||
resolution: {integrity: sha512-34EI42cYZxJF59Iht6RDM5xDun5EdhV8CbJcTe+mYx97XMHLNYA6RrH9r/ZOZX3CetVCYfBEU9oAY9h3sZarsw==}
|
||||
peerDependencies:
|
||||
'@types/react': ^16.8 || ^17.0 || ^18.0
|
||||
'@types/react-dom': ^16.8 || ^17.0 || ^18.0
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
react-native: '>=0.59'
|
||||
redux: ^4 || ^5.0.0-beta.0
|
||||
'@types/react': ^18.2.41
|
||||
'@types/react-dom': ^18.2.17
|
||||
react: ^18.0
|
||||
react-dom: ^18.0
|
||||
react-native: '>=0.71'
|
||||
redux: ^5.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
@ -11078,16 +11062,12 @@ packages:
|
||||
redux:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
'@types/hoist-non-react-statics': 3.3.1
|
||||
'@types/react': 18.2.42
|
||||
'@types/react-dom': 18.2.17
|
||||
'@types/use-sync-external-store': 0.0.3
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-is: 18.2.0
|
||||
redux: 4.2.1
|
||||
redux: 5.0.0
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
@ -11329,26 +11309,25 @@ packages:
|
||||
resolution: {integrity: sha512-GHESQC+Y0PV98ZBoaC6br6cDOsNiM1Cu4UleGMqMWCXX03jIr3BoozYVrRkLVVAl4sC216chakMnZOu6SwNdGA==}
|
||||
dev: false
|
||||
|
||||
/redux-remember@4.2.2(redux@4.2.1):
|
||||
/redux-remember@4.2.2(redux@5.0.0):
|
||||
resolution: {integrity: sha512-1pY3FNk70uZ7Djya/SXkwL13hu0T6iVYSVMFqUApR4n3BDoGYmmaSouX8T3Y1Rg2pmZFaWw7e8ZaOAH82s8IiA==}
|
||||
peerDependencies:
|
||||
redux: '*'
|
||||
dependencies:
|
||||
redux: 4.2.1
|
||||
redux: 5.0.0
|
||||
dev: false
|
||||
|
||||
/redux-thunk@2.4.2(redux@4.2.1):
|
||||
resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==}
|
||||
/redux-thunk@3.1.0(redux@5.0.0):
|
||||
resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==}
|
||||
peerDependencies:
|
||||
redux: ^4
|
||||
redux: ^5.0.0
|
||||
dependencies:
|
||||
redux: 4.2.1
|
||||
redux: 5.0.0
|
||||
dev: false
|
||||
|
||||
/redux@4.2.1:
|
||||
resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.5
|
||||
/redux@5.0.0:
|
||||
resolution: {integrity: sha512-blLIYmYetpZMET6Q6uCY7Jtl/Im5OBldy+vNPauA8vvsdqyt66oep4EUpAMWNHauTC6xa9JuRPhRB72rY82QGA==}
|
||||
dev: false
|
||||
|
||||
/reflect.getprototypeof@1.0.3:
|
||||
resolution: {integrity: sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==}
|
||||
@ -11452,8 +11431,8 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/reselect@4.1.8:
|
||||
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==}
|
||||
/reselect@5.0.1:
|
||||
resolution: {integrity: sha512-D72j2ubjgHpvuCiORWkOUxndHJrxDaSolheiz5CO+roz8ka97/4msh2E8F5qay4GawR5vzBt5MkbDHT+Rdy/Wg==}
|
||||
dev: false
|
||||
|
||||
/resize-observer-polyfill@1.5.1:
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
|
||||
@ -9,20 +9,14 @@ import {
|
||||
shiftKeyPressed,
|
||||
} from 'features/ui/store/hotkeysSlice';
|
||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import React, { memo } from 'react';
|
||||
import { isHotkeyPressed, useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
const globalHotkeysSelector = createSelector(
|
||||
const globalHotkeysSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ hotkeys }) => {
|
||||
const { shift, ctrl, meta } = hotkeys;
|
||||
return { shift, ctrl, meta };
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createLogWriter } from '@roarr/browser-log-writer';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { ROARR, Roarr } from 'roarr';
|
||||
import {
|
||||
@ -13,22 +12,14 @@ import {
|
||||
logger,
|
||||
} from './logger';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ system }) => {
|
||||
const { consoleLogLevel, shouldLogToConsole } = system;
|
||||
const selector = createMemoizedSelector(stateSelector, ({ system }) => {
|
||||
const { consoleLogLevel, shouldLogToConsole } = system;
|
||||
|
||||
return {
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
consoleLogLevel,
|
||||
shouldLogToConsole,
|
||||
};
|
||||
});
|
||||
|
||||
export const useLogger = (namespace: LoggerNamespace) => {
|
||||
const { consoleLogLevel, shouldLogToConsole } = useAppSelector(selector);
|
||||
|
@ -0,0 +1,12 @@
|
||||
import { createSelectorCreator, lruMemoize } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
/**
|
||||
* A memoized selector creator that uses LRU cache and lodash's isEqual for equality check.
|
||||
*/
|
||||
export const createMemoizedSelector = createSelectorCreator({
|
||||
memoize: lruMemoize,
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
});
|
@ -1,10 +1,10 @@
|
||||
import { AnyAction } from '@reduxjs/toolkit';
|
||||
import { UnknownAction } from '@reduxjs/toolkit';
|
||||
import { isAnyGraphBuilt } from 'features/nodes/store/actions';
|
||||
import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice';
|
||||
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
||||
import { Graph } from 'services/api/types';
|
||||
|
||||
export const actionSanitizer = <A extends AnyAction>(action: A): A => {
|
||||
export const actionSanitizer = <A extends UnknownAction>(action: A): A => {
|
||||
if (isAnyGraphBuilt(action)) {
|
||||
if (action.payload.nodes) {
|
||||
const sanitizedNodes: Graph['nodes'] = {};
|
||||
|
@ -1,11 +1,10 @@
|
||||
import type { TypedAddListener, TypedStartListening } from '@reduxjs/toolkit';
|
||||
import {
|
||||
AnyAction,
|
||||
UnknownAction,
|
||||
ListenerEffect,
|
||||
addListener,
|
||||
createListenerMiddleware,
|
||||
} from '@reduxjs/toolkit';
|
||||
|
||||
import type { AppDispatch, RootState } from 'app/store/store';
|
||||
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
|
||||
import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts';
|
||||
@ -87,7 +86,7 @@ export const addAppListener = addListener as TypedAddListener<
|
||||
>;
|
||||
|
||||
export type AppListenerEffect = ListenerEffect<
|
||||
AnyAction,
|
||||
UnknownAction,
|
||||
RootState,
|
||||
AppDispatch
|
||||
>;
|
||||
|
@ -52,7 +52,11 @@ export const addBoardIdSelectedListener = () => {
|
||||
const { data: boardImagesData } =
|
||||
imagesApi.endpoints.listImages.select(queryArgs)(getState());
|
||||
|
||||
if (boardImagesData) {
|
||||
if (
|
||||
boardImagesData &&
|
||||
boardIdSelected.match(action) &&
|
||||
action.payload.selectedImageName
|
||||
) {
|
||||
const firstImage = imagesSelectors.selectAll(boardImagesData)[0];
|
||||
const selectedImage = imagesSelectors.selectById(
|
||||
boardImagesData,
|
||||
|
@ -24,7 +24,7 @@ export const addSocketQueueItemStatusChangedEventListener = () => {
|
||||
dispatch(
|
||||
queueApi.util.updateQueryData('listQueueItems', undefined, (draft) => {
|
||||
queueItemsAdapter.updateOne(draft, {
|
||||
id: queue_item.item_id,
|
||||
id: String(queue_item.item_id),
|
||||
changes: queue_item,
|
||||
});
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {
|
||||
AnyAction,
|
||||
ThunkDispatch,
|
||||
UnknownAction,
|
||||
autoBatchEnhancer,
|
||||
combineReducers,
|
||||
configureStore,
|
||||
@ -27,7 +27,6 @@ import { createStore as createIDBKeyValStore, get, set } from 'idb-keyval';
|
||||
import dynamicMiddlewares from 'redux-dynamic-middlewares';
|
||||
import { Driver, rememberEnhancer, rememberReducer } from 'redux-remember';
|
||||
import { api } from 'services/api';
|
||||
import { authToastMiddleware } from 'services/api/authToastMiddleware';
|
||||
import { STORAGE_PREFIX } from './constants';
|
||||
import { serialize } from './enhancers/reduxRemember/serialize';
|
||||
import { unserialize } from './enhancers/reduxRemember/unserialize';
|
||||
@ -90,8 +89,16 @@ const idbKeyValDriver: Driver = {
|
||||
export const createStore = (uniqueStoreKey?: string, persist = true) =>
|
||||
configureStore({
|
||||
reducer: rememberedRootReducer,
|
||||
enhancers: (existingEnhancers) => {
|
||||
const _enhancers = existingEnhancers.concat(autoBatchEnhancer());
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware({
|
||||
serializableCheck: false,
|
||||
immutableCheck: false,
|
||||
})
|
||||
.concat(api.middleware)
|
||||
.concat(dynamicMiddlewares)
|
||||
.prepend(listenerMiddleware.middleware),
|
||||
enhancers: (getDefaultEnhancers) => {
|
||||
const _enhancers = getDefaultEnhancers().concat(autoBatchEnhancer());
|
||||
if (persist) {
|
||||
_enhancers.push(
|
||||
rememberEnhancer(idbKeyValDriver, rememberedKeys, {
|
||||
@ -106,15 +113,6 @@ export const createStore = (uniqueStoreKey?: string, persist = true) =>
|
||||
}
|
||||
return _enhancers;
|
||||
},
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware({
|
||||
serializableCheck: false,
|
||||
immutableCheck: false,
|
||||
})
|
||||
.concat(api.middleware)
|
||||
.concat(dynamicMiddlewares)
|
||||
.concat(authToastMiddleware)
|
||||
.prepend(listenerMiddleware.middleware),
|
||||
devTools: {
|
||||
actionSanitizer,
|
||||
stateSanitizer,
|
||||
@ -145,6 +143,6 @@ export type AppGetState = ReturnType<
|
||||
>;
|
||||
export type RootState = ReturnType<ReturnType<typeof createStore>['getState']>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type AppThunkDispatch = ThunkDispatch<RootState, any, AnyAction>;
|
||||
export type AppThunkDispatch = ThunkDispatch<RootState, any, UnknownAction>;
|
||||
export type AppDispatch = ReturnType<typeof createStore>['dispatch'];
|
||||
export const stateSelector = (state: RootState) => state;
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export const defaultSelectorOptions = {
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
};
|
@ -12,7 +12,6 @@
|
||||
* - increment it in `onPaneClick`
|
||||
* - `useEffect()` to close the menu when `globalContextMenuCloseTrigger` changes
|
||||
*/
|
||||
|
||||
import {
|
||||
Menu,
|
||||
MenuButton,
|
||||
|
@ -19,7 +19,6 @@ import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { stopPastePropagation } from 'common/util/stopPastePropagation';
|
||||
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
|
||||
import { clamp } from 'lodash-es';
|
||||
|
||||
import {
|
||||
FocusEvent,
|
||||
KeyboardEvent,
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import {
|
||||
@ -20,7 +19,7 @@ import { useUploadImageMutation } from 'services/api/endpoints/images';
|
||||
import { PostUploadAction } from 'services/api/types';
|
||||
import ImageUploadOverlay from './ImageUploadOverlay';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ gallery }, activeTabName) => {
|
||||
let postUploadAction: PostUploadAction = { type: 'TOAST' };
|
||||
@ -39,8 +38,7 @@ const selector = createSelector(
|
||||
autoAddBoardId,
|
||||
postUploadAction,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
type ImageUploaderProps = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterAll } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -10,7 +9,7 @@ import i18n from 'i18next';
|
||||
import { forEach } from 'lodash-es';
|
||||
import { getConnectedEdges } from 'reactflow';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
(
|
||||
{ controlAdapters, generation, system, nodes, dynamicPrompts },
|
||||
@ -125,8 +124,7 @@ const selector = createSelector(
|
||||
}
|
||||
|
||||
return { isReady: !reasons.length, reasons };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
export const useIsReadyToEnqueue = () => {
|
||||
|
@ -1,5 +1,4 @@
|
||||
// https://stackoverflow.com/a/73731908
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function useSingleAndDoubleClick(
|
||||
|
@ -1,16 +1,7 @@
|
||||
import { Box, chakra, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import { Layer, Stage } from 'react-konva';
|
||||
import useCanvasDragMove from 'features/canvas/hooks/useCanvasDragMove';
|
||||
import useCanvasHotkeys from 'features/canvas/hooks/useCanvasHotkeys';
|
||||
import useCanvasMouseDown from 'features/canvas/hooks/useCanvasMouseDown';
|
||||
@ -18,11 +9,17 @@ import useCanvasMouseMove from 'features/canvas/hooks/useCanvasMouseMove';
|
||||
import useCanvasMouseOut from 'features/canvas/hooks/useCanvasMouseOut';
|
||||
import useCanvasMouseUp from 'features/canvas/hooks/useCanvasMouseUp';
|
||||
import useCanvasWheel from 'features/canvas/hooks/useCanvasZoom';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { canvasResized } from 'features/canvas/store/canvasSlice';
|
||||
import {
|
||||
setCanvasBaseLayer,
|
||||
setCanvasStage,
|
||||
} from 'features/canvas/util/konvaInstanceProvider';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import { Layer, Stage } from 'react-konva';
|
||||
import IAICanvasBoundingBoxOverlay from './IAICanvasBoundingBoxOverlay';
|
||||
import IAICanvasGrid from './IAICanvasGrid';
|
||||
import IAICanvasIntermediateImage from './IAICanvasIntermediateImage';
|
||||
@ -35,9 +32,9 @@ import IAICanvasStatusText from './IAICanvasStatusText';
|
||||
import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox';
|
||||
import IAICanvasToolPreview from './IAICanvasToolPreview';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, isStagingSelector],
|
||||
({ canvas }, isStaging) => {
|
||||
const {
|
||||
isMaskEnabled,
|
||||
stageScale,
|
||||
@ -83,8 +80,7 @@ const selector = createSelector(
|
||||
shouldShowIntermediates,
|
||||
shouldAntialias,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
const ChakraStage = chakra(Stage, {
|
||||
|
@ -1,38 +1,28 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { Group, Rect } from 'react-konva';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { memo } from 'react';
|
||||
import { Group, Rect } from 'react-konva';
|
||||
|
||||
const selector = createSelector(
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const {
|
||||
boundingBoxCoordinates,
|
||||
boundingBoxDimensions,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
stageCoordinates,
|
||||
} = canvas;
|
||||
const selector = createMemoizedSelector(stateSelector, ({ canvas }) => {
|
||||
const {
|
||||
boundingBoxCoordinates,
|
||||
boundingBoxDimensions,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
stageCoordinates,
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
boundingBoxCoordinates,
|
||||
boundingBoxDimensions,
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
stageCoordinates,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
boundingBoxCoordinates,
|
||||
boundingBoxDimensions,
|
||||
shouldDarkenOutsideBoundingBox,
|
||||
stageCoordinates,
|
||||
stageDimensions,
|
||||
stageScale,
|
||||
};
|
||||
});
|
||||
const IAICanvasBoundingBoxOverlay = () => {
|
||||
const {
|
||||
boundingBoxCoordinates,
|
||||
|
@ -1,26 +1,16 @@
|
||||
// Grid drawing adapted from https://longviewcoder.com/2021/12/08/konva-a-better-grid/
|
||||
|
||||
import { useColorMode, useToken } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { isEqual, range } from 'lodash-es';
|
||||
|
||||
import { range } from 'lodash-es';
|
||||
import { ReactNode, memo, useCallback, useLayoutEffect, useState } from 'react';
|
||||
import { Group, Line as KonvaLine } from 'react-konva';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const { stageScale, stageCoordinates, stageDimensions } = canvas;
|
||||
return { stageScale, stageCoordinates, stageDimensions };
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
||||
const { stageScale, stageCoordinates, stageDimensions } = canvas;
|
||||
return { stageScale, stageCoordinates, stageDimensions };
|
||||
});
|
||||
|
||||
const IAICanvasGrid = () => {
|
||||
const { stageScale, stageCoordinates, stageDimensions } =
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { $authToken } from 'app/store/nanostores/authToken';
|
||||
import { memo } from 'react';
|
||||
import { Image } from 'react-konva';
|
||||
|
@ -2,31 +2,22 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { ImageConfig } from 'konva/lib/shapes/Image';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { Image as KonvaImage } from 'react-konva';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ system, canvas }) => {
|
||||
const { denoiseProgress } = system;
|
||||
const { boundingBox } = canvas.layerState.stagingArea;
|
||||
const { batchIds } = canvas;
|
||||
const selector = createSelector([stateSelector], ({ system, canvas }) => {
|
||||
const { denoiseProgress } = system;
|
||||
const { boundingBox } = canvas.layerState.stagingArea;
|
||||
const { batchIds } = canvas;
|
||||
|
||||
return {
|
||||
boundingBox,
|
||||
progressImage:
|
||||
denoiseProgress && batchIds.includes(denoiseProgress.batch_id)
|
||||
? denoiseProgress.progress_image
|
||||
: undefined,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
boundingBox,
|
||||
progressImage:
|
||||
denoiseProgress && batchIds.includes(denoiseProgress.batch_id)
|
||||
? denoiseProgress.progress_image
|
||||
: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
type Props = Omit<ImageConfig, 'image'>;
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { RectConfig } from 'konva/lib/shapes/Rect';
|
||||
import { Rect } from 'react-konva';
|
||||
|
||||
import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
||||
import Konva from 'konva';
|
||||
import { RectConfig } from 'konva/lib/shapes/Rect';
|
||||
import { isNumber } from 'lodash-es';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Rect } from 'react-konva';
|
||||
|
||||
export const canvasMaskCompositerSelector = createSelector(
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
export const canvasMaskCompositerSelector = createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ canvas }) => {
|
||||
const { maskColor, stageCoordinates, stageDimensions, stageScale } = canvas;
|
||||
|
||||
return {
|
||||
|
@ -1,22 +1,15 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { Group, Line } from 'react-konva';
|
||||
import { isCanvasMaskLine } from 'features/canvas/store/canvasTypes';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { memo } from 'react';
|
||||
import { Group, Line } from 'react-konva';
|
||||
|
||||
export const canvasLinesSelector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
export const canvasLinesSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas }) => {
|
||||
return { objects: canvas.layerState.objects };
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,35 +1,25 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { Group, Line, Rect } from 'react-konva';
|
||||
import {
|
||||
isCanvasBaseImage,
|
||||
isCanvasBaseLine,
|
||||
isCanvasEraseRect,
|
||||
isCanvasFillRect,
|
||||
} from 'features/canvas/store/canvasTypes';
|
||||
import IAICanvasImage from './IAICanvasImage';
|
||||
import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
||||
import { memo } from 'react';
|
||||
import { Group, Line, Rect } from 'react-konva';
|
||||
import IAICanvasImage from './IAICanvasImage';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
layerState: { objects },
|
||||
} = canvas;
|
||||
return {
|
||||
objects,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
||||
const {
|
||||
layerState: { objects },
|
||||
} = canvas;
|
||||
return {
|
||||
objects,
|
||||
};
|
||||
});
|
||||
|
||||
const IAICanvasObjectRenderer = () => {
|
||||
const { objects } = useAppSelector(selector);
|
||||
|
@ -1,46 +1,37 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import { Group, Rect } from 'react-konva';
|
||||
import IAICanvasImage from './IAICanvasImage';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
layerState,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
boundingBoxCoordinates: stageBoundingBoxCoordinates,
|
||||
boundingBoxDimensions: stageBoundingBoxDimensions,
|
||||
} = canvas;
|
||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
||||
const {
|
||||
layerState,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
boundingBoxCoordinates: stageBoundingBoxCoordinates,
|
||||
boundingBoxDimensions: stageBoundingBoxDimensions,
|
||||
} = canvas;
|
||||
|
||||
const { selectedImageIndex, images, boundingBox } = layerState.stagingArea;
|
||||
const { selectedImageIndex, images, boundingBox } = layerState.stagingArea;
|
||||
|
||||
return {
|
||||
currentStagingAreaImage:
|
||||
images.length > 0 && selectedImageIndex !== undefined
|
||||
? images[selectedImageIndex]
|
||||
: undefined,
|
||||
isOnFirstImage: selectedImageIndex === 0,
|
||||
isOnLastImage: selectedImageIndex === images.length - 1,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
x: boundingBox?.x ?? stageBoundingBoxCoordinates.x,
|
||||
y: boundingBox?.y ?? stageBoundingBoxCoordinates.y,
|
||||
width: boundingBox?.width ?? stageBoundingBoxDimensions.width,
|
||||
height: boundingBox?.height ?? stageBoundingBoxDimensions.height,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
currentStagingAreaImage:
|
||||
images.length > 0 && selectedImageIndex !== undefined
|
||||
? images[selectedImageIndex]
|
||||
: undefined,
|
||||
isOnFirstImage: selectedImageIndex === 0,
|
||||
isOnLastImage: selectedImageIndex === images.length - 1,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
x: boundingBox?.x ?? stageBoundingBoxCoordinates.x,
|
||||
y: boundingBox?.y ?? stageBoundingBoxCoordinates.y,
|
||||
width: boundingBox?.width ?? stageBoundingBoxDimensions.width,
|
||||
height: boundingBox?.height ?? stageBoundingBoxDimensions.height,
|
||||
};
|
||||
});
|
||||
|
||||
type Props = GroupConfig;
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { ButtonGroup, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { stagingAreaImageSaved } from 'features/canvas/store/actions';
|
||||
import {
|
||||
commitStagingAreaImage,
|
||||
discardStagedImages,
|
||||
@ -11,10 +14,6 @@ import {
|
||||
setShouldShowStagingImage,
|
||||
setShouldShowStagingOutline,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -28,30 +27,25 @@ import {
|
||||
FaTimes,
|
||||
} from 'react-icons/fa';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { stagingAreaImageSaved } from 'features/canvas/store/actions';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
layerState: {
|
||||
stagingArea: { images, selectedImageIndex },
|
||||
},
|
||||
shouldShowStagingOutline,
|
||||
shouldShowStagingImage,
|
||||
} = canvas;
|
||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
||||
const {
|
||||
layerState: {
|
||||
stagingArea: { images, selectedImageIndex },
|
||||
},
|
||||
shouldShowStagingOutline,
|
||||
shouldShowStagingImage,
|
||||
} = canvas;
|
||||
|
||||
return {
|
||||
currentIndex: selectedImageIndex,
|
||||
total: images.length,
|
||||
currentStagingAreaImage:
|
||||
images.length > 0 ? images[selectedImageIndex] : undefined,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
currentIndex: selectedImageIndex,
|
||||
total: images.length,
|
||||
currentStagingAreaImage:
|
||||
images.length > 0 ? images[selectedImageIndex] : undefined,
|
||||
shouldShowStagingImage,
|
||||
shouldShowStagingOutline,
|
||||
};
|
||||
});
|
||||
|
||||
const IAICanvasStagingAreaToolbar = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -1,74 +1,65 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import GenerationModeStatusText from 'features/parameters/components/Parameters/Canvas/GenerationModeStatusText';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import roundToHundreth from 'features/canvas/util/roundToHundreth';
|
||||
import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos';
|
||||
import GenerationModeStatusText from 'features/parameters/components/Parameters/Canvas/GenerationModeStatusText';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos';
|
||||
|
||||
const warningColor = 'var(--invokeai-colors-warning-500)';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const {
|
||||
stageDimensions: { width: stageWidth, height: stageHeight },
|
||||
stageCoordinates: { x: stageX, y: stageY },
|
||||
boundingBoxDimensions: { width: boxWidth, height: boxHeight },
|
||||
scaledBoundingBoxDimensions: {
|
||||
width: scaledBoxWidth,
|
||||
height: scaledBoxHeight,
|
||||
},
|
||||
boundingBoxCoordinates: { x: boxX, y: boxY },
|
||||
stageScale,
|
||||
shouldShowCanvasDebugInfo,
|
||||
layer,
|
||||
boundingBoxScaleMethod,
|
||||
shouldPreserveMaskedArea,
|
||||
} = canvas;
|
||||
|
||||
let boundingBoxColor = 'inherit';
|
||||
|
||||
if (
|
||||
(boundingBoxScaleMethod === 'none' &&
|
||||
(boxWidth < 512 || boxHeight < 512)) ||
|
||||
(boundingBoxScaleMethod === 'manual' &&
|
||||
scaledBoxWidth * scaledBoxHeight < 512 * 512)
|
||||
) {
|
||||
boundingBoxColor = warningColor;
|
||||
}
|
||||
|
||||
const activeLayerColor = layer === 'mask' ? warningColor : 'inherit';
|
||||
|
||||
return {
|
||||
activeLayerColor,
|
||||
layer,
|
||||
boundingBoxColor,
|
||||
boundingBoxCoordinatesString: `(${roundToHundreth(
|
||||
boxX
|
||||
)}, ${roundToHundreth(boxY)})`,
|
||||
boundingBoxDimensionsString: `${boxWidth}×${boxHeight}`,
|
||||
scaledBoundingBoxDimensionsString: `${scaledBoxWidth}×${scaledBoxHeight}`,
|
||||
canvasCoordinatesString: `${roundToHundreth(stageX)}×${roundToHundreth(
|
||||
stageY
|
||||
)}`,
|
||||
canvasDimensionsString: `${stageWidth}×${stageHeight}`,
|
||||
canvasScaleString: Math.round(stageScale * 100),
|
||||
shouldShowCanvasDebugInfo,
|
||||
shouldShowBoundingBox: boundingBoxScaleMethod !== 'auto',
|
||||
shouldShowScaledBoundingBox: boundingBoxScaleMethod !== 'none',
|
||||
shouldPreserveMaskedArea,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
const selector = createMemoizedSelector([stateSelector], ({ canvas }) => {
|
||||
const {
|
||||
stageDimensions: { width: stageWidth, height: stageHeight },
|
||||
stageCoordinates: { x: stageX, y: stageY },
|
||||
boundingBoxDimensions: { width: boxWidth, height: boxHeight },
|
||||
scaledBoundingBoxDimensions: {
|
||||
width: scaledBoxWidth,
|
||||
height: scaledBoxHeight,
|
||||
},
|
||||
boundingBoxCoordinates: { x: boxX, y: boxY },
|
||||
stageScale,
|
||||
shouldShowCanvasDebugInfo,
|
||||
layer,
|
||||
boundingBoxScaleMethod,
|
||||
shouldPreserveMaskedArea,
|
||||
} = canvas;
|
||||
|
||||
let boundingBoxColor = 'inherit';
|
||||
|
||||
if (
|
||||
(boundingBoxScaleMethod === 'none' &&
|
||||
(boxWidth < 512 || boxHeight < 512)) ||
|
||||
(boundingBoxScaleMethod === 'manual' &&
|
||||
scaledBoxWidth * scaledBoxHeight < 512 * 512)
|
||||
) {
|
||||
boundingBoxColor = warningColor;
|
||||
}
|
||||
);
|
||||
|
||||
const activeLayerColor = layer === 'mask' ? warningColor : 'inherit';
|
||||
|
||||
return {
|
||||
activeLayerColor,
|
||||
layer,
|
||||
boundingBoxColor,
|
||||
boundingBoxCoordinatesString: `(${roundToHundreth(boxX)}, ${roundToHundreth(
|
||||
boxY
|
||||
)})`,
|
||||
boundingBoxDimensionsString: `${boxWidth}×${boxHeight}`,
|
||||
scaledBoundingBoxDimensionsString: `${scaledBoxWidth}×${scaledBoxHeight}`,
|
||||
canvasCoordinatesString: `${roundToHundreth(stageX)}×${roundToHundreth(
|
||||
stageY
|
||||
)}`,
|
||||
canvasDimensionsString: `${stageWidth}×${stageHeight}`,
|
||||
canvasScaleString: Math.round(stageScale * 100),
|
||||
shouldShowCanvasDebugInfo,
|
||||
shouldShowBoundingBox: boundingBoxScaleMethod !== 'auto',
|
||||
shouldShowScaledBoundingBox: boundingBoxScaleMethod !== 'none',
|
||||
shouldPreserveMaskedArea,
|
||||
};
|
||||
});
|
||||
|
||||
const IAICanvasStatusText = () => {
|
||||
const {
|
||||
|
@ -1,15 +1,13 @@
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import roundToHundreth from 'features/canvas/util/roundToHundreth';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const cursorPositionSelector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const cursorPositionSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas }) => {
|
||||
const { cursorPosition } = canvas;
|
||||
|
||||
const { cursorX, cursorY } = cursorPosition
|
||||
@ -21,11 +19,6 @@ const cursorPositionSelector = createSelector(
|
||||
cursorY
|
||||
)})`,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,20 +1,18 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { Circle, Group } from 'react-konva';
|
||||
import {
|
||||
COLOR_PICKER_SIZE,
|
||||
COLOR_PICKER_STROKE_RADIUS,
|
||||
} from 'features/canvas/util/constants';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { memo } from 'react';
|
||||
import { Circle, Group } from 'react-konva';
|
||||
|
||||
const canvasBrushPreviewSelector = createSelector(
|
||||
canvasSelector,
|
||||
(canvas) => {
|
||||
const canvasBrushPreviewSelector = createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ canvas }) => {
|
||||
const {
|
||||
cursorPosition,
|
||||
brushSize,
|
||||
@ -105,11 +103,6 @@ const canvasBrushPreviewSelector = createSelector(
|
||||
dotRadius: 1.5 / stageScale,
|
||||
clip,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
@ -17,13 +17,11 @@ import Konva from 'konva';
|
||||
import { GroupConfig } from 'konva/lib/Group';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { Group, Rect, Transformer } from 'react-konva';
|
||||
|
||||
const boundingBoxPreviewSelector = createSelector(
|
||||
const boundingBoxPreviewSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas, generation }) => {
|
||||
const {
|
||||
@ -51,11 +49,6 @@ const boundingBoxPreviewSelector = createSelector(
|
||||
hitStrokeWidth: 20 / stageScale,
|
||||
aspectRatio,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Box, ButtonGroup, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||
@ -7,10 +8,7 @@ import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
|
||||
import { canvasMaskSavedToGallery } from 'features/canvas/store/actions';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
clearMask,
|
||||
setIsMaskEnabled,
|
||||
@ -19,17 +17,15 @@ import {
|
||||
setShouldPreserveMaskedArea,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { rgbaColorToString } from 'features/canvas/util/colorToString';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaMask, FaSave, FaTrash } from 'react-icons/fa';
|
||||
|
||||
export const selector = createSelector(
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
export const selector = createMemoizedSelector(
|
||||
[stateSelector, isStagingSelector],
|
||||
({ canvas }, isStaging) => {
|
||||
const { maskColor, layer, isMaskEnabled, shouldPreserveMaskedArea } =
|
||||
canvas;
|
||||
|
||||
@ -41,11 +37,6 @@ export const selector = createSelector(
|
||||
shouldPreserveMaskedArea,
|
||||
isStaging,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
const IAICanvasMaskOptions = () => {
|
||||
|
@ -1,18 +1,15 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { redo } from 'features/canvas/store/canvasSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaRedo } from 'react-icons/fa';
|
||||
|
||||
import { redo } from 'features/canvas/store/canvasSlice';
|
||||
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const canvasRedoSelector = createSelector(
|
||||
const canvasRedoSelector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ canvas }, activeTabName) => {
|
||||
const { futureLayerStates } = canvas;
|
||||
@ -21,11 +18,6 @@ const canvasRedoSelector = createSelector(
|
||||
canRedo: futureLayerStates.length > 0,
|
||||
activeTabName,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
|
||||
import ClearCanvasHistoryButtonModal from 'features/canvas/components/ClearCanvasHistoryButtonModal';
|
||||
import {
|
||||
setShouldAntialias,
|
||||
setShouldAutoSave,
|
||||
@ -16,17 +17,14 @@ import {
|
||||
setShouldShowIntermediates,
|
||||
setShouldSnapToGrid,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaWrench } from 'react-icons/fa';
|
||||
import ClearCanvasHistoryButtonModal from 'features/canvas/components/ClearCanvasHistoryButtonModal';
|
||||
|
||||
export const canvasControlsSelector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
export const canvasControlsSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas }) => {
|
||||
const {
|
||||
shouldAutoSave,
|
||||
shouldCropToBoundingBoxOnSave,
|
||||
@ -50,11 +48,6 @@ export const canvasControlsSelector = createSelector(
|
||||
shouldRestrictStrokesToBox,
|
||||
shouldAntialias,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ButtonGroup, Flex, Box } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { Box, ButtonGroup, Flex } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIColorPicker from 'common/components/IAIColorPicker';
|
||||
@ -14,10 +14,9 @@ import {
|
||||
setBrushSize,
|
||||
setTool,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { clamp, isEqual } from 'lodash-es';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { RgbaColor } from 'react-colorful';
|
||||
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
@ -29,7 +28,7 @@ import {
|
||||
FaSlidersH,
|
||||
} from 'react-icons/fa';
|
||||
|
||||
export const selector = createSelector(
|
||||
export const selector = createMemoizedSelector(
|
||||
[stateSelector, isStagingSelector],
|
||||
({ canvas }, isStaging) => {
|
||||
const { tool, brushColor, brushSize } = canvas;
|
||||
@ -40,11 +39,6 @@ export const selector = createSelector(
|
||||
brushColor,
|
||||
brushSize,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Box, ButtonGroup, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIMantineSelect from 'common/components/IAIMantineSelect';
|
||||
import { useCopyImageToClipboard } from 'common/hooks/useCopyImageToClipboard';
|
||||
import { useImageUploadButton } from 'common/hooks/useImageUploadButton';
|
||||
import { useSingleAndDoubleClick } from 'common/hooks/useSingleAndDoubleClick';
|
||||
import {
|
||||
@ -25,8 +26,6 @@ import {
|
||||
LAYER_NAMES_DICT,
|
||||
} from 'features/canvas/store/canvasTypes';
|
||||
import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
|
||||
import { useCopyImageToClipboard } from 'common/hooks/useCopyImageToClipboard';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -46,7 +45,7 @@ import IAICanvasSettingsButtonPopover from './IAICanvasSettingsButtonPopover';
|
||||
import IAICanvasToolChooserOptions from './IAICanvasToolChooserOptions';
|
||||
import IAICanvasUndoButton from './IAICanvasUndoButton';
|
||||
|
||||
export const selector = createSelector(
|
||||
export const selector = createMemoizedSelector(
|
||||
[stateSelector, isStagingSelector],
|
||||
({ canvas }, isStaging) => {
|
||||
const { tool, shouldCropToBoundingBoxOnSave, layer, isMaskEnabled } =
|
||||
@ -59,11 +58,6 @@ export const selector = createSelector(
|
||||
layer,
|
||||
shouldCropToBoundingBoxOnSave,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,18 +1,15 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { FaUndo } from 'react-icons/fa';
|
||||
|
||||
import { undo } from 'features/canvas/store/canvasSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaUndo } from 'react-icons/fa';
|
||||
|
||||
const canvasUndoSelector = createSelector(
|
||||
const canvasUndoSelector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ canvas }, activeTabName) => {
|
||||
const { pastLayerStates } = canvas;
|
||||
@ -21,11 +18,6 @@ const canvasUndoSelector = createSelector(
|
||||
canUndo: pastLayerStates.length > 0,
|
||||
activeTabName,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,21 +1,18 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
setIsMovingStage,
|
||||
setStageCoordinates,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector, isStagingSelector],
|
||||
(canvas, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, isStagingSelector],
|
||||
({ canvas }, isStaging) => {
|
||||
const { tool, isMovingBoundingBox } = canvas;
|
||||
return {
|
||||
tool,
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
clearMask,
|
||||
resetCanvasInteractionState,
|
||||
@ -12,17 +10,15 @@ import {
|
||||
setShouldSnapToGrid,
|
||||
setTool,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { useRef } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { CanvasTool } from 'features/canvas/store/canvasTypes';
|
||||
import { getCanvasStage } from 'features/canvas/util/konvaInstanceProvider';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useRef } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector, activeTabNameSelector, isStagingSelector],
|
||||
(canvas, activeTabName, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector, isStagingSelector],
|
||||
({ canvas }, activeTabName, isStaging) => {
|
||||
const {
|
||||
cursorPosition,
|
||||
shouldLockBoundingBox,
|
||||
@ -42,11 +38,6 @@ const selector = createSelector(
|
||||
isMaskEnabled,
|
||||
shouldSnapToGrid,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,26 +1,23 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
addLine,
|
||||
setIsDrawing,
|
||||
setIsMovingStage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import useColorPicker from './useColorUnderCursor';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[activeTabNameSelector, stateSelector, isStagingSelector],
|
||||
(activeTabName, { canvas }, isStaging) => {
|
||||
const { tool } = canvas;
|
||||
return {
|
||||
tool,
|
||||
|
@ -1,25 +1,22 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
addPointToCurrentLine,
|
||||
setCursorPosition,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import useColorPicker from './useColorUnderCursor';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[activeTabNameSelector, stateSelector, isStagingSelector],
|
||||
(activeTabName, { canvas }, isStaging) => {
|
||||
const { tool, isDrawing } = canvas;
|
||||
return {
|
||||
tool,
|
||||
|
@ -1,25 +1,22 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
canvasSelector,
|
||||
isStagingSelector,
|
||||
} from 'features/canvas/store/canvasSelectors';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
// addPointToCurrentEraserLine,
|
||||
addPointToCurrentLine,
|
||||
setIsDrawing,
|
||||
setIsMovingStage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
|
||||
const selector = createSelector(
|
||||
[activeTabNameSelector, canvasSelector, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[activeTabNameSelector, stateSelector, isStagingSelector],
|
||||
(activeTabName, { canvas }, isStaging) => {
|
||||
const { tool, isDrawing } = canvas;
|
||||
return {
|
||||
tool,
|
||||
|
@ -1,24 +1,23 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
setStageCoordinates,
|
||||
setStageScale,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { clamp, isEqual } from 'lodash-es';
|
||||
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
import {
|
||||
CANVAS_SCALE_BY,
|
||||
MAX_CANVAS_SCALE,
|
||||
MIN_CANVAS_SCALE,
|
||||
} from 'features/canvas/util/constants';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import { clamp, isEqual } from 'lodash-es';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
|
||||
const selector = createSelector(
|
||||
[canvasSelector],
|
||||
(canvas) => {
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas }) => {
|
||||
const { isMoveStageKeyHeld, stageScale } = canvas;
|
||||
return {
|
||||
isMoveStageKeyHeld,
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { RootState, stateSelector } from 'app/store/store';
|
||||
import { CanvasImage, CanvasState, isCanvasBaseImage } from './canvasTypes';
|
||||
import { CanvasImage, isCanvasBaseImage } from './canvasTypes';
|
||||
|
||||
export const canvasSelector = (state: RootState): CanvasState => state.canvas;
|
||||
|
||||
export const isStagingSelector = createSelector(
|
||||
export const isStagingSelector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ canvas }) =>
|
||||
canvas.batchIds.length > 0 ||
|
||||
|
@ -8,25 +8,24 @@ import {
|
||||
Flex,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||
import {
|
||||
changeBoardReset,
|
||||
isModalOpenChanged,
|
||||
} from 'features/changeBoardModal/store/slice';
|
||||
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
||||
import {
|
||||
useAddImagesToBoardMutation,
|
||||
useRemoveImagesFromBoardMutation,
|
||||
} from 'services/api/endpoints/images';
|
||||
import {
|
||||
changeBoardReset,
|
||||
isModalOpenChanged,
|
||||
} from 'features/changeBoardModal/store/slice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ changeBoardModal }) => {
|
||||
const { isModalOpen, imagesToChange } = changeBoardModal;
|
||||
@ -35,8 +34,7 @@ const selector = createSelector(
|
||||
isModalOpen,
|
||||
imagesToChange,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
const ChangeBoardModal = () => {
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
} from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import ParamControlAdapterModel from './parameters/ParamControlAdapterModel';
|
||||
import ParamControlAdapterWeight from './parameters/ParamControlAdapterWeight';
|
||||
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Box, Flex, Spinner } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIDndImage from 'common/components/IAIDndImage';
|
||||
import IAIDndImageIcon from 'common/components/IAIDndImageIcon';
|
||||
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
|
||||
@ -33,7 +32,7 @@ type Props = {
|
||||
isSmall?: boolean;
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters, gallery, system }) => {
|
||||
const { pendingControlImages } = controlAdapters;
|
||||
@ -45,8 +44,7 @@ const selector = createSelector(
|
||||
autoAddBoardId,
|
||||
isConnected,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
const ControlAdapterImagePreview = ({ isSmall, id }: Props) => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ButtonGroup, Divider, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import ControlAdapterConfig from 'features/controlAdapters/components/ControlAdapterConfig';
|
||||
import { useAddControlAdapter } from 'features/controlAdapters/hooks/useAddControlAdapter';
|
||||
import {
|
||||
selectAllControlNets,
|
||||
selectAllIPAdapters,
|
||||
@ -19,9 +19,8 @@ import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { Fragment, memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaPlus } from 'react-icons/fa';
|
||||
import { useAddControlAdapter } from 'features/controlAdapters/hooks/useAddControlAdapter';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector],
|
||||
({ controlAdapters }) => {
|
||||
const activeLabel: string[] = [];
|
||||
@ -68,8 +67,7 @@ const selector = createSelector(
|
||||
activeLabel: activeLabel.join(', '),
|
||||
isError, // TODO: Add some visual indicator that the control adapters are in an error state
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
const ControlAdaptersCollapse = () => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled';
|
||||
@ -18,14 +17,10 @@ type ParamControlAdapterModelProps = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ generation }) => {
|
||||
const { model } = generation;
|
||||
return { mainModel: model };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, ({ generation }) => {
|
||||
const { model } = generation;
|
||||
return { mainModel: model };
|
||||
});
|
||||
|
||||
const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => {
|
||||
const isEnabled = useControlAdapterIsEnabled(id);
|
||||
|
@ -1,53 +1,47 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineSearchableSelect, {
|
||||
IAISelectDataType,
|
||||
} from 'common/components/IAIMantineSearchableSelect';
|
||||
import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled';
|
||||
import { useControlAdapterProcessorNode } from 'features/controlAdapters/hooks/useControlAdapterProcessorNode';
|
||||
import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants';
|
||||
import { controlAdapterProcessortTypeChanged } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { ControlAdapterProcessorType } from 'features/controlAdapters/store/types';
|
||||
import { configSelector } from 'features/system/store/configSelectors';
|
||||
import { map } from 'lodash-es';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants';
|
||||
import { controlAdapterProcessortTypeChanged } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { ControlAdapterProcessorType } from 'features/controlAdapters/store/types';
|
||||
|
||||
type Props = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
configSelector,
|
||||
(config) => {
|
||||
const controlNetProcessors: IAISelectDataType[] = map(
|
||||
CONTROLNET_PROCESSORS,
|
||||
(p) => ({
|
||||
value: p.type,
|
||||
label: p.label,
|
||||
})
|
||||
const selector = createMemoizedSelector(configSelector, (config) => {
|
||||
const controlNetProcessors: IAISelectDataType[] = map(
|
||||
CONTROLNET_PROCESSORS,
|
||||
(p) => ({
|
||||
value: p.type,
|
||||
label: p.label,
|
||||
})
|
||||
)
|
||||
.sort((a, b) =>
|
||||
// sort 'none' to the top
|
||||
a.value === 'none'
|
||||
? -1
|
||||
: b.value === 'none'
|
||||
? 1
|
||||
: a.label.localeCompare(b.label)
|
||||
)
|
||||
.sort((a, b) =>
|
||||
// sort 'none' to the top
|
||||
a.value === 'none'
|
||||
? -1
|
||||
: b.value === 'none'
|
||||
? 1
|
||||
: a.label.localeCompare(b.label)
|
||||
)
|
||||
.filter(
|
||||
(d) =>
|
||||
!config.sd.disabledControlNetProcessors.includes(
|
||||
d.value as ControlAdapterProcessorType
|
||||
)
|
||||
);
|
||||
.filter(
|
||||
(d) =>
|
||||
!config.sd.disabledControlNetProcessors.includes(
|
||||
d.value as ControlAdapterProcessorType
|
||||
)
|
||||
);
|
||||
|
||||
return controlNetProcessors;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return controlNetProcessors;
|
||||
});
|
||||
|
||||
const ParamControlAdapterProcessorSelect = ({ id }: Props) => {
|
||||
const isEnabled = useControlAdapterIsEnabled(id);
|
||||
|
@ -1,17 +1,14 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapter = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => selectControlAdapterById(controlAdapters, id),
|
||||
defaultSelectorOptions
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -1,26 +1,21 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterBeginEndStepPct = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const cn = selectControlAdapterById(controlAdapters, id);
|
||||
return cn
|
||||
? {
|
||||
beginStepPct: cn.beginStepPct,
|
||||
endStepPct: cn.endStepPct,
|
||||
}
|
||||
: undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const cn = selectControlAdapterById(controlAdapters, id);
|
||||
return cn
|
||||
? {
|
||||
beginStepPct: cn.beginStepPct,
|
||||
endStepPct: cn.endStepPct,
|
||||
}
|
||||
: undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,18 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterControlImage = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.controlImage,
|
||||
defaultSelectorOptions
|
||||
selectControlAdapterById(controlAdapters, id)?.controlImage
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNet } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterControlMode = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNet(ca)) {
|
||||
return ca.controlMode;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNet(ca)) {
|
||||
return ca.controlMode;
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,18 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterIsEnabled = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.isEnabled ?? false,
|
||||
defaultSelectorOptions
|
||||
selectControlAdapterById(controlAdapters, id)?.isEnabled ?? false
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -1,18 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterModel = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.model,
|
||||
defaultSelectorOptions
|
||||
selectControlAdapterById(controlAdapters, id)?.model
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterProcessedControlImage = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processedControlImage
|
||||
: undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processedControlImage
|
||||
: undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterProcessorNode = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processorNode
|
||||
: undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processorNode
|
||||
: undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterProcessorType = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processorType
|
||||
: undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
? ca.processorType
|
||||
: undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterResizeMode = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNetOrT2IAdapter(ca)) {
|
||||
return ca.resizeMode;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNetOrT2IAdapter(ca)) {
|
||||
return ca.resizeMode;
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,25 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterShouldAutoConfig = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNetOrT2IAdapter(ca)) {
|
||||
return ca.shouldAutoConfig;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
createMemoizedSelector(stateSelector, ({ controlAdapters }) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNetOrT2IAdapter(ca)) {
|
||||
return ca.shouldAutoConfig;
|
||||
}
|
||||
return undefined;
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
|
@ -1,18 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterType = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.type,
|
||||
defaultSelectorOptions
|
||||
selectControlAdapterById(controlAdapters, id)?.type
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -1,18 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useMemo } from 'react';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectControlAdapterById } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useControlAdapterWeight = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ controlAdapters }) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.weight,
|
||||
defaultSelectorOptions
|
||||
selectControlAdapterById(controlAdapters, id)?.weight
|
||||
),
|
||||
[id]
|
||||
);
|
||||
|
@ -35,7 +35,9 @@ import {
|
||||
isT2IAdapter,
|
||||
} from './types';
|
||||
|
||||
export const caAdapter = createEntityAdapter<ControlAdapterConfig>();
|
||||
export const caAdapter = createEntityAdapter<ControlAdapterConfig, string>({
|
||||
selectId: (ca) => ca.id,
|
||||
});
|
||||
|
||||
export const {
|
||||
selectById: selectControlAdapterById,
|
||||
@ -259,7 +261,7 @@ export const controlAdaptersSlice = createSlice({
|
||||
return;
|
||||
}
|
||||
|
||||
const update: Update<ControlNetConfig | T2IAdapterConfig> = {
|
||||
const update: Update<ControlNetConfig | T2IAdapterConfig, string> = {
|
||||
id,
|
||||
changes: { model },
|
||||
};
|
||||
@ -398,7 +400,7 @@ export const controlAdaptersSlice = createSlice({
|
||||
return;
|
||||
}
|
||||
|
||||
const update: Update<ControlNetConfig | T2IAdapterConfig> = {
|
||||
const update: Update<ControlNetConfig | T2IAdapterConfig, string> = {
|
||||
id,
|
||||
changes: { shouldAutoConfig: !cn.shouldAutoConfig },
|
||||
};
|
||||
|
@ -425,7 +425,7 @@ export type ControlAdapterConfig =
|
||||
|
||||
export type ControlAdapterType = ControlAdapterConfig['type'];
|
||||
|
||||
export type ControlAdaptersState = EntityState<ControlAdapterConfig> & {
|
||||
export type ControlAdaptersState = EntityState<ControlAdapterConfig, string> & {
|
||||
pendingControlImages: string[];
|
||||
};
|
||||
|
||||
|
@ -9,16 +9,11 @@ import {
|
||||
Flex,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldConfirmOnDelete } from 'features/system/store/systemSlice';
|
||||
import { some } from 'lodash-es';
|
||||
import { ChangeEvent, memo, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { imageDeletionConfirmed } from 'features/deleteImageModal/store/actions';
|
||||
import {
|
||||
getImageUsage,
|
||||
@ -29,9 +24,13 @@ import {
|
||||
isModalOpenChanged,
|
||||
} from 'features/deleteImageModal/store/slice';
|
||||
import { ImageUsage } from 'features/deleteImageModal/store/types';
|
||||
import { setShouldConfirmOnDelete } from 'features/system/store/systemSlice';
|
||||
import { some } from 'lodash-es';
|
||||
import { ChangeEvent, memo, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ImageUsageMessage from './ImageUsageMessage';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, selectImageUsage],
|
||||
(state, imagesUsage) => {
|
||||
const { system, config, deleteImageModal } = state;
|
||||
@ -58,8 +57,7 @@ const selector = createSelector(
|
||||
isModalOpen,
|
||||
imageUsageSummary,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
const DeleteImageModal = () => {
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
import { some } from 'lodash-es';
|
||||
import { ImageUsage } from './types';
|
||||
import { selectControlAdapterAll } from 'features/controlAdapters/store/controlAdaptersSlice';
|
||||
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
|
||||
import { isImageFieldInputInstance } from 'features/nodes/types/field';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
import { some } from 'lodash-es';
|
||||
import { ImageUsage } from './types';
|
||||
|
||||
export const getImageUsage = (state: RootState, image_name: string) => {
|
||||
const { generation, canvas, nodes, controlAdapters } = state;
|
||||
@ -41,7 +40,7 @@ export const getImageUsage = (state: RootState, image_name: string) => {
|
||||
return imageUsage;
|
||||
};
|
||||
|
||||
export const selectImageUsage = createSelector(
|
||||
export const selectImageUsage = createMemoizedSelector(
|
||||
[(state: RootState) => state],
|
||||
(state) => {
|
||||
const { imagesToDelete } = state.deleteImageModal;
|
||||
@ -55,6 +54,5 @@ export const selectImageUsage = createSelector(
|
||||
);
|
||||
|
||||
return imagesUsage;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import type { Modifier } from '@dnd-kit/core';
|
||||
import { getEventCoordinates } from '@dnd-kit/utilities';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const selectZoom = createSelector(
|
||||
const selectZoom = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ nodes }, activeTabName) =>
|
||||
activeTabName === 'nodes' ? nodes.viewport.zoom : 1
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
|
||||
import ParamDynamicPromptsPreview from './ParamDynamicPromptsPreview';
|
||||
import ParamDynamicPromptsSeedBehaviour from './ParamDynamicPromptsSeedBehaviour';
|
||||
@ -14,7 +14,7 @@ const ParamDynamicPromptsCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const selectActiveLabel = useMemo(
|
||||
() =>
|
||||
createSelector(stateSelector, ({ dynamicPrompts }) => {
|
||||
createMemoizedSelector(stateSelector, ({ dynamicPrompts }) => {
|
||||
const count = dynamicPrompts.prompts.length;
|
||||
if (count > 1) {
|
||||
return t('dynamicPrompts.promptsWithCount_other', {
|
||||
|
@ -1,21 +1,16 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { combinatorialToggled } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { combinatorialToggled } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { combinatorial } = state.dynamicPrompts;
|
||||
const selector = createMemoizedSelector(stateSelector, (state) => {
|
||||
const { combinatorial } = state.dynamicPrompts;
|
||||
|
||||
return { combinatorial };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return { combinatorial };
|
||||
});
|
||||
|
||||
const ParamDynamicPromptsCombinatorial = () => {
|
||||
const { combinatorial } = useAppSelector(selector);
|
||||
|
@ -1,33 +1,28 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover/IAIInformationalPopover';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { memo, useCallback } from 'react';
|
||||
import {
|
||||
maxPromptsChanged,
|
||||
maxPromptsReset,
|
||||
} from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover/IAIInformationalPopover';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { maxPrompts, combinatorial } = state.dynamicPrompts;
|
||||
const { min, sliderMax, inputMax } =
|
||||
state.config.sd.dynamicPrompts.maxPrompts;
|
||||
const selector = createMemoizedSelector(stateSelector, (state) => {
|
||||
const { maxPrompts, combinatorial } = state.dynamicPrompts;
|
||||
const { min, sliderMax, inputMax } =
|
||||
state.config.sd.dynamicPrompts.maxPrompts;
|
||||
|
||||
return {
|
||||
maxPrompts,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
isDisabled: !combinatorial,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
maxPrompts,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
isDisabled: !combinatorial,
|
||||
};
|
||||
});
|
||||
|
||||
const ParamDynamicPromptsMaxPrompts = () => {
|
||||
const { maxPrompts, min, sliderMax, inputMax, isDisabled } =
|
||||
|
@ -8,31 +8,26 @@ import {
|
||||
Spinner,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover/IAIInformationalPopover';
|
||||
import ScrollableContent from 'features/nodes/components/sidePanel/ScrollableContent';
|
||||
import { memo } from 'react';
|
||||
import { FaCircleExclamation } from 'react-icons/fa6';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaCircleExclamation } from 'react-icons/fa6';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { isLoading, isError, prompts, parsingError } = state.dynamicPrompts;
|
||||
const selector = createMemoizedSelector(stateSelector, (state) => {
|
||||
const { isLoading, isError, prompts, parsingError } = state.dynamicPrompts;
|
||||
|
||||
return {
|
||||
prompts,
|
||||
parsingError,
|
||||
isError,
|
||||
isLoading,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
prompts,
|
||||
parsingError,
|
||||
isError,
|
||||
isLoading,
|
||||
};
|
||||
});
|
||||
|
||||
const listItemStyles: ChakraProps['sx'] = {
|
||||
'&::marker': { color: 'base.500', _dark: { color: 'base.500' } },
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
|
||||
@ -10,18 +9,14 @@ import { memo, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ gallery }) => {
|
||||
const { autoAddBoardId, autoAssignBoardOnClick } = gallery;
|
||||
const selector = createMemoizedSelector([stateSelector], ({ gallery }) => {
|
||||
const { autoAddBoardId, autoAssignBoardOnClick } = gallery;
|
||||
|
||||
return {
|
||||
autoAddBoardId,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
autoAddBoardId,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
});
|
||||
|
||||
const BoardAutoAddSelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -1,25 +1,24 @@
|
||||
import { MenuGroup, MenuItem, MenuList } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import {
|
||||
IAIContextMenu,
|
||||
IAIContextMenuProps,
|
||||
} from 'common/components/IAIContextMenu';
|
||||
import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { BoardId } from 'features/gallery/store/types';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { MouseEvent, memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaDownload, FaPlus } from 'react-icons/fa';
|
||||
import { useBulkDownloadImagesMutation } from 'services/api/endpoints/images';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
import { BoardDTO } from 'services/api/types';
|
||||
import { menuListMotionProps } from 'theme/components/menu';
|
||||
import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems';
|
||||
import NoBoardContextMenuItems from './NoBoardContextMenuItems';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useBulkDownloadImagesMutation } from 'services/api/endpoints/images';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
|
||||
type Props = {
|
||||
board?: BoardDTO;
|
||||
@ -39,15 +38,11 @@ const BoardContextMenu = ({
|
||||
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ gallery }) => {
|
||||
const isAutoAdd = gallery.autoAddBoardId === board_id;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
return { isAutoAdd, autoAssignBoardOnClick };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
createMemoizedSelector(stateSelector, ({ gallery }) => {
|
||||
const isAutoAdd = gallery.autoAddBoardId === board_id;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
return { isAutoAdd, autoAssignBoardOnClick };
|
||||
}),
|
||||
[board_id]
|
||||
);
|
||||
|
||||
|
@ -1,26 +1,21 @@
|
||||
import { Collapse, Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import DeleteBoardModal from 'features/gallery/components/Boards/DeleteBoardModal';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import { memo, useState } from 'react';
|
||||
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
|
||||
import { BoardDTO } from 'services/api/types';
|
||||
import DeleteBoardModal from 'features/gallery/components/Boards/DeleteBoardModal';
|
||||
import AddBoardButton from './AddBoardButton';
|
||||
import BoardsSearch from './BoardsSearch';
|
||||
import GalleryBoard from './GalleryBoard';
|
||||
import NoBoardBoard from './NoBoardBoard';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ gallery }) => {
|
||||
const { selectedBoardId, boardSearchText } = gallery;
|
||||
return { selectedBoardId, boardSearchText };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector([stateSelector], ({ gallery }) => {
|
||||
const { selectedBoardId, boardSearchText } = gallery;
|
||||
return { selectedBoardId, boardSearchText };
|
||||
});
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
@ -5,10 +5,9 @@ import {
|
||||
InputGroup,
|
||||
InputRightElement,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { boardSearchTextChanged } from 'features/gallery/store/gallerySlice';
|
||||
import {
|
||||
ChangeEvent,
|
||||
@ -20,14 +19,10 @@ import {
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ gallery }) => {
|
||||
const { boardSearchText } = gallery;
|
||||
return { boardSearchText };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector([stateSelector], ({ gallery }) => {
|
||||
const { boardSearchText } = gallery;
|
||||
return { boardSearchText };
|
||||
});
|
||||
|
||||
const BoardsSearch = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -9,19 +9,21 @@ import {
|
||||
Text,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIDroppable from 'common/components/IAIDroppable';
|
||||
import SelectionOverlay from 'common/components/SelectionOverlay';
|
||||
import { AddToBoardDropData } from 'features/dnd/types';
|
||||
import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
|
||||
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
|
||||
import {
|
||||
autoAddBoardIdChanged,
|
||||
boardIdSelected,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import { memo, useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaUser } from 'react-icons/fa';
|
||||
import {
|
||||
useGetBoardAssetsTotalQuery,
|
||||
@ -30,9 +32,6 @@ import {
|
||||
} from 'services/api/endpoints/boards';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { BoardDTO } from 'services/api/types';
|
||||
import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
|
||||
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface GalleryBoardProps {
|
||||
board: BoardDTO;
|
||||
@ -48,20 +47,15 @@ const GalleryBoard = ({
|
||||
const dispatch = useAppDispatch();
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ gallery }) => {
|
||||
const isSelectedForAutoAdd =
|
||||
board.board_id === gallery.autoAddBoardId;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
createMemoizedSelector(stateSelector, ({ gallery }) => {
|
||||
const isSelectedForAutoAdd = board.board_id === gallery.autoAddBoardId;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
|
||||
return {
|
||||
isSelectedForAutoAdd,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
),
|
||||
return {
|
||||
isSelectedForAutoAdd,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
}),
|
||||
[board.board_id]
|
||||
);
|
||||
|
||||
|
@ -1,38 +1,33 @@
|
||||
import { Box, Flex, Image, Text, Tooltip } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import InvokeAILogoImage from 'assets/images/logo.png';
|
||||
import IAIDroppable from 'common/components/IAIDroppable';
|
||||
import SelectionOverlay from 'common/components/SelectionOverlay';
|
||||
import { RemoveFromBoardDropData } from 'features/dnd/types';
|
||||
import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
|
||||
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
|
||||
import {
|
||||
autoAddBoardIdChanged,
|
||||
boardIdSelected,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import { memo, useCallback, useMemo, useState } from 'react';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
|
||||
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
useGetBoardAssetsTotalQuery,
|
||||
useGetBoardImagesTotalQuery,
|
||||
} from 'services/api/endpoints/boards';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
interface Props {
|
||||
isSelected: boolean;
|
||||
}
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ gallery }) => {
|
||||
const { autoAddBoardId, autoAssignBoardOnClick } = gallery;
|
||||
return { autoAddBoardId, autoAssignBoardOnClick };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, ({ gallery }) => {
|
||||
const { autoAddBoardId, autoAssignBoardOnClick } = gallery;
|
||||
return { autoAddBoardId, autoAssignBoardOnClick };
|
||||
});
|
||||
|
||||
const NoBoardBoard = memo(({ isSelected }: Props) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -9,8 +9,8 @@ import {
|
||||
Skeleton,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
@ -43,7 +43,7 @@ const DeleteBoardModal = (props: Props) => {
|
||||
|
||||
const selectImageUsageSummary = useMemo(
|
||||
() =>
|
||||
createSelector([stateSelector], (state) => {
|
||||
createMemoizedSelector([stateSelector], (state) => {
|
||||
const allImageUsage = (boardImageNames ?? []).map((imageName) =>
|
||||
getImageUsage(state, imageName)
|
||||
);
|
||||
|
@ -1,6 +1,3 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
import {
|
||||
ButtonGroup,
|
||||
Flex,
|
||||
@ -8,8 +5,9 @@ import {
|
||||
MenuButton,
|
||||
MenuList,
|
||||
} from '@chakra-ui/react';
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { upscaleRequested } from 'app/store/middleware/listenerMiddleware/listeners/upscaleRequested';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
@ -45,7 +43,7 @@ import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||
import { menuListMotionProps } from 'theme/components/menu';
|
||||
|
||||
const currentImageButtonsSelector = createSelector(
|
||||
const currentImageButtonsSelector = createMemoizedSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ gallery, system, ui, config }, activeTabName) => {
|
||||
const { isConnected, shouldConfirmOnDelete, denoiseProgress } = system;
|
||||
@ -72,11 +70,6 @@ const currentImageButtonsSelector = createSelector(
|
||||
lastSelectedImage,
|
||||
shouldFetchMetadataFromApi,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
import CurrentImageButtons from './CurrentImageButtons';
|
||||
import CurrentImagePreview from './CurrentImagePreview';
|
||||
import { memo } from 'react';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box, Flex, Image } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/dist/query';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIDndImage from 'common/components/IAIDndImage';
|
||||
@ -9,19 +9,18 @@ import {
|
||||
TypesafeDraggableData,
|
||||
TypesafeDroppableData,
|
||||
} from 'features/dnd/types';
|
||||
import ImageMetadataViewer from 'features/gallery/components/ImageMetadataViewer/ImageMetadataViewer';
|
||||
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
||||
import { useNextPrevImage } from 'features/gallery/hooks/useNextPrevImage';
|
||||
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaImage } from 'react-icons/fa';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import ImageMetadataViewer from 'features/gallery/components/ImageMetadataViewer/ImageMetadataViewer';
|
||||
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const imagesSelector = createSelector(
|
||||
export const imagesSelector = createMemoizedSelector(
|
||||
[stateSelector, selectLastSelectedImage],
|
||||
({ ui, system }, lastSelectedImage) => {
|
||||
const {
|
||||
@ -38,11 +37,6 @@ export const imagesSelector = createSelector(
|
||||
shouldShowProgressInViewer,
|
||||
shouldAntialiasProgressImage,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,21 +1,16 @@
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import { Button, Flex, Text } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
(state) => {
|
||||
const { selectedBoardId } = state.gallery;
|
||||
const selector = createMemoizedSelector([stateSelector], (state) => {
|
||||
const { selectedBoardId } = state.gallery;
|
||||
|
||||
return { selectedBoardId };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return { selectedBoardId };
|
||||
});
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import {
|
||||
@ -16,25 +16,17 @@ import { ChangeEvent, memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaWrench } from 'react-icons/fa';
|
||||
import BoardAutoAddSelect from './Boards/BoardAutoAddSelect';
|
||||
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
(state) => {
|
||||
const {
|
||||
galleryImageMinimumWidth,
|
||||
shouldAutoSwitch,
|
||||
autoAssignBoardOnClick,
|
||||
} = state.gallery;
|
||||
const selector = createMemoizedSelector([stateSelector], (state) => {
|
||||
const { galleryImageMinimumWidth, shouldAutoSwitch, autoAssignBoardOnClick } =
|
||||
state.gallery;
|
||||
|
||||
return {
|
||||
galleryImageMinimumWidth,
|
||||
shouldAutoSwitch,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
galleryImageMinimumWidth,
|
||||
shouldAutoSwitch,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
});
|
||||
|
||||
const GallerySettingsPopover = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { MenuList } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
IAIContextMenu,
|
||||
IAIContextMenuProps,
|
||||
@ -6,27 +9,19 @@ import {
|
||||
import { MouseEvent, memo, useCallback } from 'react';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import { menuListMotionProps } from 'theme/components/menu';
|
||||
import SingleSelectionMenuItems from './SingleSelectionMenuItems';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import MultipleSelectionMenuItems from './MultipleSelectionMenuItems';
|
||||
import SingleSelectionMenuItems from './SingleSelectionMenuItems';
|
||||
|
||||
type Props = {
|
||||
imageDTO: ImageDTO | undefined;
|
||||
children: IAIContextMenuProps<HTMLDivElement>['children'];
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ gallery }) => {
|
||||
const selectionCount = gallery.selection.length;
|
||||
const selector = createMemoizedSelector([stateSelector], ({ gallery }) => {
|
||||
const selectionCount = gallery.selection.length;
|
||||
|
||||
return { selectionCount };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return { selectionCount };
|
||||
});
|
||||
|
||||
const ImageContextMenu = ({ imageDTO, children }: Props) => {
|
||||
const { selectionCount } = useAppSelector(selector);
|
||||
|
@ -8,31 +8,26 @@ import {
|
||||
VStack,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { FaImages, FaServer } from 'react-icons/fa';
|
||||
import { galleryViewChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaImages, FaServer } from 'react-icons/fa';
|
||||
import BoardsList from './Boards/BoardsList/BoardsList';
|
||||
import GalleryBoardName from './GalleryBoardName';
|
||||
import GallerySettingsPopover from './GallerySettingsPopover';
|
||||
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
(state) => {
|
||||
const { galleryView } = state.gallery;
|
||||
const selector = createMemoizedSelector([stateSelector], (state) => {
|
||||
const { galleryView } = state.gallery;
|
||||
|
||||
return {
|
||||
galleryView,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
galleryView,
|
||||
};
|
||||
});
|
||||
|
||||
const ImageGalleryContent = () => {
|
||||
const { t } = useTranslation();
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
|
||||
import { selectionChanged } from 'features/gallery/store/gallerySlice';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { MouseEvent, useCallback, useMemo } from 'react';
|
||||
import { useListImagesQuery } from 'services/api/endpoints/images';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import { imagesSelectors } from 'services/api/util';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { selectionChanged } from 'features/gallery/store/gallerySlice';
|
||||
|
||||
const selector = createSelector(
|
||||
const selector = createMemoizedSelector(
|
||||
[stateSelector, selectListImagesBaseQueryArgs],
|
||||
({ gallery }, queryArgs) => {
|
||||
const selection = gallery.selection;
|
||||
@ -19,8 +18,7 @@ const selector = createSelector(
|
||||
queryArgs,
|
||||
selection,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
||||
export const useMultiselect = (imageDTO?: ImageDTO) => {
|
||||
|
@ -1,20 +1,20 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
|
||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||
import { clamp, isEqual } from 'lodash-es';
|
||||
import { IMAGE_LIMIT } from 'features/gallery/store/types';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { useCallback } from 'react';
|
||||
import { boardsApi } from 'services/api/endpoints/boards';
|
||||
import {
|
||||
imagesApi,
|
||||
useLazyListImagesQuery,
|
||||
} from 'services/api/endpoints/images';
|
||||
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
|
||||
import { IMAGE_LIMIT } from 'features/gallery/store/types';
|
||||
import { ListImagesArgs } from 'services/api/types';
|
||||
import { imagesAdapter } from 'services/api/util';
|
||||
|
||||
export const nextPrevImageButtonsSelector = createSelector(
|
||||
export const nextPrevImageButtonsSelector = createMemoizedSelector(
|
||||
[stateSelector, selectListImagesBaseQueryArgs],
|
||||
(state, baseQueryArgs) => {
|
||||
const { data, status } =
|
||||
@ -80,11 +80,6 @@ export const nextPrevImageButtonsSelector = createSelector(
|
||||
prevImage,
|
||||
queryArgs,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { ListImagesArgs } from 'services/api/types';
|
||||
import {
|
||||
ASSETS_CATEGORIES,
|
||||
@ -10,13 +9,12 @@ import {
|
||||
|
||||
export const gallerySelector = (state: RootState) => state.gallery;
|
||||
|
||||
export const selectLastSelectedImage = createSelector(
|
||||
export const selectLastSelectedImage = createMemoizedSelector(
|
||||
(state: RootState) => state,
|
||||
(state) => state.gallery.selection[state.gallery.selection.length - 1],
|
||||
defaultSelectorOptions
|
||||
(state) => state.gallery.selection[state.gallery.selection.length - 1]
|
||||
);
|
||||
|
||||
export const selectListImagesBaseQueryArgs = createSelector(
|
||||
export const selectListImagesBaseQueryArgs = createMemoizedSelector(
|
||||
[(state: RootState) => state],
|
||||
(state) => {
|
||||
const { selectedBoardId, galleryView } = state.gallery;
|
||||
@ -32,6 +30,5 @@ export const selectListImagesBaseQueryArgs = createSelector(
|
||||
};
|
||||
|
||||
return listImagesBaseQueryArgs;
|
||||
},
|
||||
defaultSelectorOptions
|
||||
}
|
||||
);
|
||||
|
@ -1,26 +1,21 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { size } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamLoraList from './ParamLoraList';
|
||||
import ParamLoRASelect from './ParamLoraSelect';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const loraCount = size(state.lora.loras);
|
||||
return {
|
||||
activeLabel: loraCount > 0 ? `${loraCount} Active` : undefined,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, (state) => {
|
||||
const loraCount = size(state.lora.loras);
|
||||
return {
|
||||
activeLabel: loraCount > 0 ? `${loraCount} Active` : undefined,
|
||||
};
|
||||
});
|
||||
|
||||
const ParamLoraCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
|
@ -1,19 +1,14 @@
|
||||
import { Divider, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { map } from 'lodash-es';
|
||||
import ParamLora from './ParamLora';
|
||||
import { memo } from 'react';
|
||||
import ParamLora from './ParamLora';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ lora }) => {
|
||||
return { lorasArray: map(lora.loras) };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, ({ lora }) => {
|
||||
return { lorasArray: map(lora.loras) };
|
||||
});
|
||||
|
||||
const ParamLoraList = () => {
|
||||
const { lorasArray } = useAppSelector(selector);
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { RootState, stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||
import IAIMantineSelectItemWithTooltip from 'common/components/IAIMantineSelectItemWithTooltip';
|
||||
import { loraAdded } from 'features/lora/store/loraSlice';
|
||||
@ -13,13 +12,9 @@ import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ lora }) => ({
|
||||
loras: lora.loras,
|
||||
}),
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, ({ lora }) => ({
|
||||
loras: lora.loras,
|
||||
}));
|
||||
|
||||
const ParamLoRASelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SelectItem } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Flex, Text } from '@chakra-ui/react';
|
||||
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
MainModelConfigEntity,
|
||||
|
@ -16,7 +16,6 @@ import IAIInput from 'common/components/IAIInput';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { ChangeEvent, useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useConvertMainModelsMutation } from 'services/api/endpoints/models';
|
||||
import { CheckpointModelConfig } from 'services/api/types';
|
||||
|
||||
|
@ -240,7 +240,7 @@ const modelsFilter = <
|
||||
| LoRAModelConfigEntity
|
||||
| OnnxModelConfigEntity,
|
||||
>(
|
||||
data: EntityState<T> | undefined,
|
||||
data: EntityState<T, string> | undefined,
|
||||
model_type: ModelType,
|
||||
model_format: ModelFormat | undefined,
|
||||
nameFilter: string
|
||||
|
@ -5,11 +5,10 @@ import {
|
||||
PopoverBody,
|
||||
PopoverContent,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect';
|
||||
import { useBuildNode } from 'features/nodes/hooks/useBuildNode';
|
||||
import {
|
||||
@ -62,58 +61,54 @@ const AddNodePopover = () => {
|
||||
(state) => state.nodes.connectionStartParams?.handleType
|
||||
);
|
||||
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ nodes }) => {
|
||||
// If we have a connection in progress, we need to filter the node choices
|
||||
const filteredNodeTemplates = fieldFilter
|
||||
? filter(nodes.nodeTemplates, (template) => {
|
||||
const handles =
|
||||
handleFilter == 'source' ? template.inputs : template.outputs;
|
||||
const selector = createMemoizedSelector([stateSelector], ({ nodes }) => {
|
||||
// If we have a connection in progress, we need to filter the node choices
|
||||
const filteredNodeTemplates = fieldFilter
|
||||
? filter(nodes.nodeTemplates, (template) => {
|
||||
const handles =
|
||||
handleFilter == 'source' ? template.inputs : template.outputs;
|
||||
|
||||
return some(handles, (handle) => {
|
||||
const sourceType =
|
||||
handleFilter == 'source' ? fieldFilter : handle.type;
|
||||
const targetType =
|
||||
handleFilter == 'target' ? fieldFilter : handle.type;
|
||||
return some(handles, (handle) => {
|
||||
const sourceType =
|
||||
handleFilter == 'source' ? fieldFilter : handle.type;
|
||||
const targetType =
|
||||
handleFilter == 'target' ? fieldFilter : handle.type;
|
||||
|
||||
return validateSourceAndTargetTypes(sourceType, targetType);
|
||||
});
|
||||
})
|
||||
: map(nodes.nodeTemplates);
|
||||
return validateSourceAndTargetTypes(sourceType, targetType);
|
||||
});
|
||||
})
|
||||
: map(nodes.nodeTemplates);
|
||||
|
||||
const data: NodeTemplate[] = map(filteredNodeTemplates, (template) => {
|
||||
return {
|
||||
label: template.title,
|
||||
value: template.type,
|
||||
description: template.description,
|
||||
tags: template.tags,
|
||||
};
|
||||
const data: NodeTemplate[] = map(filteredNodeTemplates, (template) => {
|
||||
return {
|
||||
label: template.title,
|
||||
value: template.type,
|
||||
description: template.description,
|
||||
tags: template.tags,
|
||||
};
|
||||
});
|
||||
|
||||
//We only want these nodes if we're not filtered
|
||||
if (fieldFilter === null) {
|
||||
data.push({
|
||||
label: t('nodes.currentImage'),
|
||||
value: 'current_image',
|
||||
description: t('nodes.currentImageDescription'),
|
||||
tags: ['progress'],
|
||||
});
|
||||
|
||||
//We only want these nodes if we're not filtered
|
||||
if (fieldFilter === null) {
|
||||
data.push({
|
||||
label: t('nodes.currentImage'),
|
||||
value: 'current_image',
|
||||
description: t('nodes.currentImageDescription'),
|
||||
tags: ['progress'],
|
||||
});
|
||||
data.push({
|
||||
label: t('nodes.notes'),
|
||||
value: 'notes',
|
||||
description: t('nodes.notesDescription'),
|
||||
tags: ['notes'],
|
||||
});
|
||||
}
|
||||
|
||||
data.push({
|
||||
label: t('nodes.notes'),
|
||||
value: 'notes',
|
||||
description: t('nodes.notesDescription'),
|
||||
tags: ['notes'],
|
||||
});
|
||||
}
|
||||
data.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
data.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
return { data };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return { data };
|
||||
});
|
||||
|
||||
const { data } = useAppSelector(selector);
|
||||
const isOpen = useAppSelector((state) => state.nodes.isAddNodePopoverOpen);
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { useToken } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useIsValidConnection } from 'features/nodes/hooks/useIsValidConnection';
|
||||
import {
|
||||
connectionEnded,
|
||||
@ -67,17 +66,13 @@ const nodeTypes = {
|
||||
// TODO: can we support reactflow? if not, we could style the attribution so it matches the app
|
||||
const proOptions: ProOptions = { hideAttribution: true };
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
({ nodes }) => {
|
||||
const { shouldSnapToGrid, selectionMode } = nodes;
|
||||
return {
|
||||
shouldSnapToGrid,
|
||||
selectionMode,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
const selector = createMemoizedSelector(stateSelector, ({ nodes }) => {
|
||||
const { shouldSnapToGrid, selectionMode } = nodes;
|
||||
return {
|
||||
shouldSnapToGrid,
|
||||
selectionMode,
|
||||
};
|
||||
});
|
||||
|
||||
export const Flow = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
||||
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||
import { memo } from 'react';
|
||||
import { ConnectionLineComponentProps, getBezierPath } from 'reactflow';
|
||||
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||
|
||||
const selector = createSelector(stateSelector, ({ nodes }) => {
|
||||
const selector = createMemoizedSelector(stateSelector, ({ nodes }) => {
|
||||
const { shouldAnimateEdges, connectionStartFieldType, shouldColorEdges } =
|
||||
nodes;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
import { getFieldColor } from './getEdgeColor';
|
||||
@ -12,31 +11,26 @@ export const makeEdgeSelector = (
|
||||
targetHandleId: string | null | undefined,
|
||||
selected?: boolean
|
||||
) =>
|
||||
createSelector(
|
||||
stateSelector,
|
||||
({ nodes }) => {
|
||||
const sourceNode = nodes.nodes.find((node) => node.id === source);
|
||||
const targetNode = nodes.nodes.find((node) => node.id === target);
|
||||
createMemoizedSelector(stateSelector, ({ nodes }) => {
|
||||
const sourceNode = nodes.nodes.find((node) => node.id === source);
|
||||
const targetNode = nodes.nodes.find((node) => node.id === target);
|
||||
|
||||
const isInvocationToInvocationEdge =
|
||||
isInvocationNode(sourceNode) && isInvocationNode(targetNode);
|
||||
const isInvocationToInvocationEdge =
|
||||
isInvocationNode(sourceNode) && isInvocationNode(targetNode);
|
||||
|
||||
const isSelected =
|
||||
sourceNode?.selected || targetNode?.selected || selected;
|
||||
const sourceType = isInvocationToInvocationEdge
|
||||
? sourceNode?.data?.outputs[sourceHandleId || '']?.type
|
||||
: undefined;
|
||||
const isSelected = sourceNode?.selected || targetNode?.selected || selected;
|
||||
const sourceType = isInvocationToInvocationEdge
|
||||
? sourceNode?.data?.outputs[sourceHandleId || '']?.type
|
||||
: undefined;
|
||||
|
||||
const stroke =
|
||||
sourceType && nodes.shouldColorEdges
|
||||
? getFieldColor(sourceType)
|
||||
: colorTokenToCssVar('base.500');
|
||||
const stroke =
|
||||
sourceType && nodes.shouldColorEdges
|
||||
? getFieldColor(sourceType)
|
||||
: colorTokenToCssVar('base.500');
|
||||
|
||||
return {
|
||||
isSelected,
|
||||
shouldAnimate: nodes.shouldAnimateEdges && isSelected,
|
||||
stroke,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
return {
|
||||
isSelected,
|
||||
shouldAnimate: nodes.shouldAnimateEdges && isSelected,
|
||||
stroke,
|
||||
};
|
||||
});
|
||||
|
@ -1,25 +1,28 @@
|
||||
import { useState, PropsWithChildren, memo, useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { Flex, Image, Text } from '@chakra-ui/react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import NodeWrapper from 'features/nodes/components/flow/nodes/common/NodeWrapper';
|
||||
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import IAIDndImage from 'common/components/IAIDndImage';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
||||
import NodeWrapper from 'features/nodes/components/flow/nodes/common/NodeWrapper';
|
||||
import { DRAG_HANDLE_CLASSNAME } from 'features/nodes/types/constants';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { motion } from 'framer-motion';
|
||||
import { PropsWithChildren, memo, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { NodeProps } from 'reactflow';
|
||||
|
||||
const selector = createSelector(stateSelector, ({ system, gallery }) => {
|
||||
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
||||
const selector = createMemoizedSelector(
|
||||
stateSelector,
|
||||
({ system, gallery }) => {
|
||||
const imageDTO = gallery.selection[gallery.selection.length - 1];
|
||||
|
||||
return {
|
||||
imageDTO,
|
||||
progressImage: system.denoiseProgress?.progress_image,
|
||||
};
|
||||
});
|
||||
return {
|
||||
imageDTO,
|
||||
progressImage: system.denoiseProgress?.progress_image,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const CurrentImageNode = (props: NodeProps) => {
|
||||
const { progressImage, imageDTO } = useSelector(selector);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user