* remove thunk for receivedOpenApiSchema and use RTK query instead. add loading state for exposed fields
* clean up
* ignore any
* fix(ui): do not log on canceled openapi.json queries
- Rely on RTK Query for the `loadSchema` query by providing a custom `jsonReplacer` in our `dynamicBaseQuery`, so we don't need to manage error state.
- Detect when the query was canceled and do not log the error message in those situations.
* feat(ui): `utilitiesApi.endpoints.loadSchema` -> `appInfoApi.endpoints.getOpenAPISchema`
- Utilities is for server actions, move this to `appInfo` bc it fits better there.
- Rename to match convention for HTTP GET queries.
- Fix inverted logic in the `matchRejected` listener (typo'd this)
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Currently translated at 74.4% (1054 of 1416 strings)
translationBot(ui): update translation (German)
Currently translated at 69.6% (986 of 1416 strings)
translationBot(ui): update translation (German)
Currently translated at 68.6% (972 of 1416 strings)
Co-authored-by: B N <berndnieschalk@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
Hardcode the options in the dropdown, don't rely on translators to fill this in.
Also, add a number of missing languages (Azerbaijani, Finnish, Hungarian, Swedish, Turkish).
Closes#5647
The alpha values in the UI are `0-1` but the backend wants `0-255`.
Previously, this was handled in `parseFIeldValue` when building the graph. In a recent release, field types were refactored and broke the alpha handling.
The logic for handling alpha values is moved into `ColorFieldInputComponent`, and `parseFieldValue` now just does no value transformations.
Though it would be a minor change, I'm leaving this function in because I don't want to change the rest of the logic except when necessary.
Closes#5616
Turns out the OpenAPI schema definition for a pydantic field with a `Literal` type annotation is different depending on the number of options.
When there is a single value (e.g. `Literal["foo"]`, this results in a `const` schema object. The schema parser didn't know how to handle this, and displayed a warning in the JS console.
This situation is now handled. When a `const` schema object is encountered, we interpret that as an `EnumField` with a single option.
I think this makes sense - if you had a truly constant value, you wouldn't make it a field, so a `const` must mean a dynamically generated enum that ended up with only a single option.
Currently translated at 40.6% (582 of 1433 strings)
translationBot(ui): update translation (Turkish)
Currently translated at 38.8% (557 of 1433 strings)
Co-authored-by: Ufuk Sarp Selçok <ilkel@live.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/tr/
Translation: InvokeAI/Web UI
The `getIntermediatesCount` query is set to `refetchOnMountOrArgsChange`. The intention was for when the settings modal opens (i.e. mounts), the `getIntermediatesCount` query is refetched. But it doesn't work - modals only mount once, there is no lazy rendering for them.
So we have to imperatively refetch, by refetching as we open the modal.
Closes#5639
* Port the command-line tools to use model_manager2
1.Reimplement the following:
- invokeai-model-install
- invokeai-merge
- invokeai-ti
To avoid breaking the original modeal manager, the udpated tools
have been renamed invokeai-model-install2 and invokeai-merge2. The
textual inversion training script should continue to work with
existing installations. The "starter" models now live in
`invokeai/configs/INITIAL_MODELS2.yaml`.
When the full model manager 2 is in place and working, I'll rename
these files and commands.
2. Add the `merge` route to the web API. This will merge two or three models,
resulting a new one.
- Note that because the model installer selectively installs the `fp16` variant
of models (rather than both 16- and 32-bit versions as previous),
the diffusers merge script will choke on any huggingface diffuserse models
that were downloaded with the new installer. Previously-downloaded models
should continue to merge correctly. I have a PR
upstream https://github.com/huggingface/diffusers/pull/6670 to fix
this.
3. (more important!)
During implementation of the CLI tools, found and fixed a number of small
runtime bugs in the model_manager2 implementation:
- During model database migration, if a registered models file was
not found on disk, the migration would be aborted. Now the
offending model is skipped with a log warning.
- Caught and fixed a condition in which the installer would download the
entire diffusers repo when the user provided a single `.safetensors`
file URL.
- Caught and fixed a condition in which the installer would raise an
exception and stop the app when a request for an unknown model's metadata
was passed to Civitai. Now an error is logged and the installer continues.
- Replaced the LoWRA starter LoRA with FlatColor. The former has been removed
from Civitai.
* fix ruff issue
---------
Co-authored-by: Lincoln Stein <lstein@gmail.com>
Currently translated at 60.8% (871 of 1432 strings)
Co-authored-by: Alexander Eichhorn <pfannkuchensack@einfach-doof.de>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
* fix(ui): download image opens in new tab
In some environments, a simple `a` element cannot trigger a download of an image. Fetching the image directly can get around this and provide more reliable download functionality.
* use hook for imageUrlToBlob so token gets sent if needed
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
* redo top panel of workflow editor
* add checkbox option to save to project, integrate save-as flow into first time saving workflow
* remove log
* remove workflowLibrary as a feature that can be disabled
* lint
* feat(ui): make SaveWorkflowAsDialog a singleton
Fixes an issue where the workflow name would erroneously be an empty string (which it should show the current workflow name).
Also makes it easier to interact with this component.
- Extract the dialog state to a hook
- Render the dialog once in `<NodeEditor />`
- Use the hook in the various buttons that should open the dialog
- Fix a few wonkily named components (pre-existing issue)
* fix(ui): when saving a never-before-saved workflow, do not append " (copy)" to the name
* fix(ui): do not obscure workflow library button with add node popover
This component is kinda janky :/ the popover content somehow renders invisibly over the button. I think it's related to the `<PopoverAnchor />.
Need to redo this in the future, but for now, making the popover render lazily fixes this.
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Adds adds ctrl/meta + scroll to change brush size on canvas.
* changed hotkeys
* new hotkey as an additional
* lint fixed"
* added ctrl scroll and removed hotkey
* using
* added fix
* feedbck_changes
* brush size change logic
* feat(ui): also check for meta key when modifying brush size
* feat(ui): add comment linking to where brush size algo was determined
---------
Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Currently translated at 10.5% (151 of 1426 strings)
translationBot(ui): update translation (Turkish)
Currently translated at 8.1% (116 of 1426 strings)
translationBot(ui): update translation (Turkish)
Currently translated at 6.6% (95 of 1426 strings)
Co-authored-by: Ufuk Sarp Selçok <ilkel@live.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/tr/
Translation: InvokeAI/Web UI
It doesn't work now that the theme is external. I'm not sure how to fix it and not sure if it really did much (I don't think I ever got autocomplete...). Maybe it can be implemented in `@invoke-ai/ui-library`.
* dont show duplicate toasts if workflow actions fail due to auth
* dynamic order by options based on projectId
* add endpointName to authtoast to makeit unique per endpoint
* lint
* update toast logic to check based on endpoint name w type safety
* fix save as endpoit name
* lint
* fix type
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
* retain id through workflow state so that we correctly update or save new
* lint
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
* feat: ✨ "Remix Image" option on images
Adds a new "remix image" option where applicable, recalls all metadata except the seed
* refactor: 🚨 lint code
* feat: ✨ "Remix Image" option on images
Adds a new "remix image" option where applicable, recalls all metadata except the seed
* refactor: 🚨 lint code
* feat: ✨ add new remix hotkey to hotkeys modal
---------
Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Currently translated at 60.0% (850 of 1415 strings)
Co-authored-by: Alexander Eichhorn <pfannkuchensack@einfach-doof.de>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/de/
Translation: InvokeAI/Web UI
Remove `trim()` from model identifier schema, which prevented parsed model identifiers from matching.
The root issue here is that model names are identifiers. This will be resolved in the model manager refactor.
Closes#5556
- Bump `@invoke-ai/ui` for updated styles
- Update regex to parse prompts with newlines
- Update styling of overlay button when prompt has an error
- Fix bug where loading and error state sometimes weren't cleared
We had a one-behind issue with recalling metadata items that had a model.
For example, when recalling LoRAs, we check against the current main model to decide whether or not the requested LoRA is compatible and may be recalled.
When recalling all params, we are often also recalling the main model, but the compat logic didn't compare against this new main model.
The logic is updated to check against the new main model, if one is being set.
Closes#5512
Currently translated at 97.3% (1365 of 1402 strings)
translationBot(ui): update translation (Italian)
Currently translated at 97.3% (1365 of 1402 strings)
translationBot(ui): update translation (Italian)
Currently translated at 97.3% (1365 of 1402 strings)
translationBot(ui): update translation (Italian)
Currently translated at 97.3% (1365 of 1402 strings)
Co-authored-by: Riccardo Giovanetti <riccardo.giovanetti@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/it/
Translation: InvokeAI/Web UI
* resolved conflicts
* changed logo and some design changes
* feedback changes
* resolved conflicts
* changed logo and some design changes
* feedback changes
* lint fixed
* added translations
* some requested changes done
* all feedback changes done and replace links in settingsmenu comp
* fixed the gap between deps verisons & chnaged heights
* feat(ui): minor about modal styling
* feat(ui): tag app endpoints with FetchOnReconnect
* fix(ui): remove unused translation string
---------
Co-authored-by: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Co-authored-by: Kent Keirsey <31807370+hipsterusername@users.noreply.github.com>
Use each language's own language for their option in the language select. This falls back to the english translation if the language name isn't translated.
Per user feedback, this is preferrable to letting them expand when the window grows.
Also bumps `react-resizable-panels` now that one of my PRs is merged to fix an issue.
- Add various brand images, organise images
- Create favicon for docs pages (light blue version of key logo)
- Rename app title to `Invoke - Community Edition`
Add `FetchOnReconnect` tag, tagging relevant queries with it. This tag is invalidated in the socketConnected listener, when it is determined that the queue changed.
- Add checks to the "recovery" logic for socket connect events to reduce the number of network requests.
- Remove the `isInitialized` state from `systemSlice` and make it a nanostore local to the socketConnected listener. It didn't need to be global state. It's also now more clearly named `isFirstConnection`.
- Export the queue status selector (minor improvement, memoizes it correctly).
- Fixed a bug where after you load more, changing boards doesn't work. The offset and limit for the list image query had some wonky logic, now resolved.
- Addressed major lag in gallery when selecting an image.
Both issues were related to the useMultiselect and useGalleryImages hooks, which caused every image in the gallery to re-render on whenever the selection changed. There's no way to memoize away this - we need to know when the selection changes. This is a longstanding issue.
The selection is only used in a callback, though - the onClick handler for an image to select it (or add it to the existing selection). We don't really need the reactivity for a callback, so we don't need to listen for changes to the selection.
The logic to handle multiple selection is moved to a new `galleryImageClicked` listener, which does all the selection right when it is needed.
The result is that gallery images no long need to do heavy re-renders on any selection change.
Besides the multiselect click handler, there was also inefficient use of DND payloads. Previously, the `IMAGE_DTOS` type had a payload of image DTO objects. This was only used to drag gallery selection into a board. There is no need to hold onto image DTOs when we have the selection state already in redux. We were recalculating this payload for every image, on every tick.
This payload is now just the board id (the only piece of information we need for this particular DND event).
- I also removed some unused DND types while making this change.
There was a lot of convoluted, janky logic related to trying to not mount the context menu's portal until its needed. This was in the library where the component was originally copied from.
I've removed that and resolved the jank, at the cost of there being an extra portal for each instance of the context menu. Don't think this is going to be an issue. If it is, the whole context menu could be refactored to be a singleton.
* ci: add docker build timout; log free space on runner before and after build
* docker: bump frontend builder to node=20.x; skip linting on build
* chore: gitignore .pnpm-store
* update code owners for docker and CI
---------
Co-authored-by: Millun Atluri <Millu@users.noreply.github.com>
I was troubleshooting a hotkeys issue on canvas and thought I had broken the tool logic in a past change so I redid it moving it to nanostores. In the end, the issue was an upstream but with the hotkeys library, but I like having tool in nanostores so I'm leaving it.
It's ephemeral interaction state anyways, doesn't need to be in redux.
There's a challenge to accomplish this due to our slice structure - the model is stored in `generationSlice`, but `canvasSlice` also needs to have awareness of it. For example, when the model changes, the canvas slice doesn't know what the previous model was, so it doesn't know whether or not to optimize the size.
This means we need to lift the "should we optimize size" information up. To do this, the `modelChanged` action creator accepts the previous model as an optional second arg.
Now the canvas has access to both the previous model and new model selection, and can decide whether or not it should optimize its size setting in the same way that the generation slice does.
Closes #5452
For some reason `ReturnType<typeof useListImagesQuery>` isn't working correctly, and destructuring `queryResult` it results in `any`, when the hook is used.
I've removed the explicit return typing so that consumers of the hook get correct types.
Workflow building would fail when a current image node was in the workflow due to the strict validation.
So we need to use the other workflow builder util first, which strips out extraneous data.
This bug was introduced during an attempt to optimize the workflow building logic, which was causing slowdowns on the workflow editor.
* do not show toast if 403 is triggered by lack of image access
* remove log
* lint
---------
Co-authored-by: Mary Hipp <maryhipp@Marys-MacBook-Air.local>
* feat(ui): get rid of convoluted socket vs appSocket redux actions
There's no need to have `socket...` and `appSocket...` actions.
I did this initially due to a misunderstanding about the sequence of handling from middleware to reducers.
* feat(ui): bump deps
Mainly bumping to get latest `redux-remember`.
A change to socket.io required a change to the types in `useSocketIO`.
* chore(ui): format
* feat(ui): add error handling to redux persistence layer
- Add an error handler to `redux-remember` config using our logger
- Add custom errors representing storage set and get failures
- Update storage driver to raise these accordingly
- wrap method to clear idbkeyval storage and tidy its logic up
* feat(ui): add debuggingLoggerMiddleware
This simply logs every action and a diff of the state change.
Due to the noise this creates, it's not added by default at all. Add it to the middlewares if you want to use it.
* feat(ui): add $socket to window if in dev mode
* fix(ui): do not enable cancel hotkeys on inputs
* fix(ui): use JSON.stringify for ROARR logger serializer
A recent change to ROARR introduced limits to the size of data that will logged. This ends up making our logs far less useful. Change the serializer back to what it was previously.
* feat(ui): change diff util, update debuggerLoggerMiddleware
The previous diff library would present deleted things as `undefined`. Unfortunately, a JSON.stringify cycle will strip those values out. The ROARR logger does this and so the diffs end up being a lot less useful, not showing removed keys.
The new diff library uses a different format for the delta that serializes nicely.
* feat(ui): add migrations to redux persistence layer
- All persisted slices must now have a slice config, consisting of their initial state and a migrate callback. The migrate callback is very simple for now, with no type safety. It adds missing properties to the state. A future enhancement might be to model the each slice's state with e.g. zod and have proper validation and types.
- Persisted slices now have a `_version` property
- The migrate callback is called inside `redux-remember`'s `unserialize` handler. I couldn't figure out a good way to put this into the reducer and do logging (reducers should have no side effects). Also I ran into a weird race condition that I couldn't figure out. And finally, the typings are tricky. This works for now.
- `generationSlice` and `canvasSlice` both need migrations for the new aspect ratio setup, this has been added
- Stuff related to persistence has been moved in to `store.ts` for simplicity
* feat(ui): clean up StorageError class
* fix(ui): scale method default is now 'auto'
* feat(ui): when changing controlnet model, enable autoconfig
* fix(ui): make embedding popover immediately accessible
Prevents hotkeys from being captured when embeddings are still loading.
The new select component appears to close itself before calling the onchange handler. This short-circuits the autoconnect logic. Tweaked so the ordering is correct.