Commit Graph

972 Commits

Author SHA1 Message Date
psychedelicious
b09008c530 feat(ui): add cancel and clear all as toggleable app feature 2025-03-18 06:48:10 +11:00
psychedelicious
23518b9830 feat(ui): useDebouncedAppSelector
Hook that replicates `useSelector`, but debounces calling the selector.
2025-03-14 20:54:58 +11:00
Mary Hipp
e5591d145f allow workflow sort options to be passed in 2025-03-13 08:27:51 -04:00
psychedelicious
6f568d48ed fix(ui): studio init action workflow loading 2025-03-13 07:10:59 +11:00
psychedelicious
a29fb18c0b feat(ui): standardize and clean up workflow loading hooks and logic 2025-03-13 07:10:59 +11:00
psychedelicious
099011000f chore(ui): lint 2025-03-12 08:00:18 +11:00
psychedelicious
1756d885f6 refactor(ui): split workflow library state into separate slice
Has no business being in the workflow state slice.
2025-03-12 08:00:18 +11:00
psychedelicious
c259899bf4 feat(ui): support for FLUX Redux in canvas
User facing:

When a FLUX main model is selected, users may now add Regional Reference Image layers.

When switching between FLUX Redux and FLUX IP Adapter, the settings will change to match the model type. (IP Adapter has weight, begin/end step, but Redux does not.) The image will be retained when switching between the two.

Otherwise it works the same way as IP Adapter - both in Global and Regional Reference Image layers.

---

Internal state handling:

Slightly awkward, but it was easiest to make FLUX Redux a second type of IP Adapter in redux state.

Global and regional reference images still have a single `ipAdapter` field, but it can have a type of `ip_adapter` or `flux_redux`.

Ideally, this field is called `config` or `settings` or something, but we are past that point. We _could_ do a migration to rename it, but I don't think it's worth the effort.

---

Other changes:
- Updated canvas layer validators to handle FLUX Redux.
- Updated model list loading logic to un-set FLUX Redux models in Canvas if they are not in the list (e.g. if the user deletes the model in the main app).
- Updated graph builders - new `addFLUXRedux` util & updated `addRegions` util.
- Updated the `buildModelsHook` util to return a hook that accepts a filter callback. This handles a discrepancy: FLUX IP Adapter does not support regional guidance, but FLUX Redux does. The Regional Guidance settings provide the filter to filter out FLUX IP Adapter models from the combined list of IP Adapter ahd Redux models.
2025-03-11 11:17:19 +11:00
psychedelicious
a89d68b93a fix(ui): hide shared on workflow library 2025-03-10 12:29:48 -04:00
psychedelicious
50657650c2 feat(ui): rough out recent workflows 2025-03-07 08:44:15 +11:00
Mary Hipp
d5c5e8e8ed another new workflow library 2025-03-07 08:44:15 +11:00
psychedelicious
07d65b8fd1 refactor(ui): workflow loading, saving and saved status tracking
This big chungus reworks and simplifies much of the logic around loading and saving workflows. It also makes some minor changes to how store the current workflow and determine if it is a draft, user workflow or default workflow.

---

The lower-level hooks to save a workflow have been revised:
- `useSaveLibraryWorkflow`: Saves a user or project workflow that has had changes made to it.
- `useCreateNewWorkflow`: Saves a workflow as a new entity.

A new higher-level hook `useSaveOrSaveAsWorkflow` is intended to be used by components. It returns a single function that:
- Constructs the workflow payload to be sent to the server
- Checks if the workflow is an existing user workflow. If so, it immediately saves (updates) that workflow.
- If it's not an existing user workflow, it opens the save as dialog so the user can choose a name for it and create a new workflow. This occurs for both draft workflows and loaded default workflows.

---

The logic to build the current redux state into a workflow - either to be saved as JSON, to update an existing user workflow, or save as - was a bit convoluted.

Changes to redux state triggered a debounced function to build the workflow, setting it in a global nanostores atom. Then, all of the functions that consumed the "built workflow" referenced this atom.

Now, this logic is strictly imperative. When a consumer wants to save a workflow, we build it on the spot. This removes a layer of indirection.

The logic is in the `useBuildWorkflowFast` hook.

---

The logic for loading a workflow is also revised. Previously, it happened in an RTK listener. You'd need to dispatch an action to load a workflow, and wouldn't know if it succeeded or not (though the listener would make a toast if the load failed).

This is now done in a callback, outside redux middleware. The callback is returned from the `useLoadWorkflow` hook.

---

Previously, we stripped the id from default workflows when loading them. Then, when saving the workflow, we built a workflow object from redux state and hit the API with it.

This has two issues:
- It relies on redux state never having an ID set when a default workflow is loaded. If we somehow ended up with a default workflow's ID in redux, when we go to save the workflow, we'd get and error or it wouldn't work, because you cannot save a default workflow. You can only save-as it.
- We do not know the default workflow from which the current workflow was loaded. And be cause we don't know the default workflow, we cannot show a thumbnail image.

The responsibilities have been shifted around a bit.

Now, when we load a workflow, we load it as-is. The default workflow IDs are saved in redux state. We can render the thumbnail, and if the user goes to save the workflow, we detect that it is a default workflow and save-as it.

---

In `App.tsx`, the long list of modals are moved into their own "isolator" component to ensure any re-renders there do not affect the rest of the app.

---

The save-workflow-as modal is restructured to be a bit simpler. Still works the same. On commercial, "save to project" will be enabled by default.

---

The workflow JSON tab uses a debounced version of "buildWorkflow" to build the workflow as JSON.

---

`buildWorkflowFast` is updated to deep-copy its _whole_ output, preventing issues where field types could accidentally get mutated. I don't think this has ever happened but we may as well be safe.

---

Fixed an issue where the edit button in the workflow list didn't open the workflow in edit mode.
2025-03-06 10:57:54 +11:00
psychedelicious
f366640d46 fix(ui): invoke button not showing loading indicator on canvas tab
On the Canvas tab, when we made the network request to enqueue a batch, we were immediately resetting the request. This effectively disabled RTKQ's tracking of the request - including the loading state.

As a result, when you click the Invoke button on the Canvas tab, it didn't show a spinner, and it was not clear that anything was happening.

The solution is simple - just await the enqueue request before resetting the tracking, same as we already did on the workflows and upscaling tabs.

I also added some extra logging messages for enqueuing, so we get the same JS console logs for each tab on success or failure.
2025-02-28 15:58:17 +11:00
psychedelicious
2e13bbbe1b refactor(ui): make all readiness checking async
This fixes the broken readiness checks introduced in the previous commit.

To support async batch generators, all of the validation of the generators needs to be async. This is problematic because a lot of the validation logic was in redux selectors, which are necessarily synchronous.

To resolve this, the readiness checks and related logic are restructured to be run async in response to redux state changes via `useEffect` (another option is to directly subscribe to redux store). These async functions then set some react state. The checks are debounced to prevent thrashing the UI.

See #7580 for more context about this issue.

Other changes:
- Fix a minor issue where empty collections were also checked against their min and max sizes, and errors were shown for all the checks. If a collection is empty, we don't need to do the min/max checks. If a collection is empty, we skip the other min/max checks and do not report those errors to the user.
- When a field is connected, do not attempt to check its value. This fixes an issue where collection fields with a connection could erroneously appear to be invalid.
- Improved error messages for batch nodes.
2025-02-26 18:25:23 +11:00
psychedelicious
42c5be16d1 tidy(ui): extract resolveBatchValues to own file 2025-02-26 18:25:23 +11:00
psychedelicious
a626387a0b feat(ui): use auto-add board as default for nodes
Board fields in the workflow editor now default to using the auto-add board by default.

**This is a change in behaviour - previously, we defaulted to no board (i.e. Uncategorized).**

There is some translation needed between the UI field values for a board and what the graph expects.

A "BoardField" is an object in the shape of `{board_id: string}`.

Valid board field values in the graph:
- undefined
- a BoardField

Value UI values and their mapping to the graph values:
- 'none' -> undefined
- 'auto' -> BoardField for the auto-add board, or if the auto-add board is Uncategorized, undefined
- undefined -> undefined (this is a fallback case with the new logic)
- a BoardField -> the same BoardField
2025-02-25 11:10:06 +11:00
Mary Hipp
637b629b95 lint 2025-02-24 11:56:16 -05:00
psychedelicious
4aaa807415 experiment(ui): show loader until studio init actions are complete 2025-02-24 11:56:16 -05:00
psychedelicious
012054acaa feat(ui): add dialog when loading workflow if unsaved changes 2025-02-21 12:24:03 +11:00
psychedelicious
4b29a2f395 refactor(ui): validateWorkflow takes a single object as arg 2025-02-20 09:08:24 +11:00
Mary Hipp
ca50f8193c add AppFeature for retryQueueItem in case we want to easily disable 2025-02-18 09:14:03 +11:00
psychedelicious
62e5b9da18 docs(ui): add comments for recent perf optimizations 2025-02-17 09:28:13 +11:00
psychedelicious
3446486f40 perf(ui): do not use memoized selector for control adapter state 2025-02-17 09:28:13 +11:00
psychedelicious
a0cdcdef57 perf(ui): debounce invoke readiness calculations 2025-02-17 09:28:13 +11:00
psychedelicious
10d9e75391 fix(ui): rtk upgrade TS issues 2025-02-17 09:28:13 +11:00
psychedelicious
479d5cc362 perf(ui): isolate a lot of root-level hooks in a memoized component 2025-02-17 09:28:13 +11:00
psychedelicious
6faed4f1ec fix(ui): remove images from node image collections when deleted 2025-02-14 14:50:56 +11:00
psychedelicious
4f85bf078a tidy(ui): import reactflow css in main theme provider 2025-02-14 14:50:56 +11:00
psychedelicious
011910a08c refactor(ui): continued reorg of components & hooks 2025-02-14 14:50:56 +11:00
psychedelicious
e7aafdfdbf feat(ui): migrate all clipboard stuff to useClipboard 2025-02-07 11:08:03 +11:00
psychedelicious
d9c2115396 feat(ui): support pasting directly to canvas 2025-02-06 12:56:21 +11:00
psychedelicious
a8eb47769a feat(ui): improved enqueue error messages 2025-02-06 07:57:26 +11:00
Riku
a4d58aab09 feat(ui): add cancel all except current queue item functionality 2025-02-04 12:23:23 +11:00
Mary Hipp
64475b8f21 feat(ui): add button to clear model cache 2025-01-30 09:18:28 -05:00
psychedelicious
57265c8869 feat(ui): rip out generator modal functionality 2025-01-17 12:48:58 +11:00
psychedelicious
bfb26af36a chore(ui): lint 2025-01-17 12:48:58 +11:00
psychedelicious
10f2c0dc9a feat(ui): support generator nodes (wip)
- Add `batch` property to field type object to differentiate between executable nodes and batch/generator nodes.
- Support for float generators
2025-01-17 12:48:58 +11:00
psychedelicious
30e33d30d5 fix(ui): handle batch group ids of "None" correctly 2025-01-17 12:34:54 +11:00
psychedelicious
ca1bd254ea feat(ui): rename "link_id" -> "batch_group_id" 2025-01-17 12:34:54 +11:00
psychedelicious
0abc0be931 fix(ui): allow batch nodes without link id (i.e. product batch nodes) to have mismatched collection sizes 2025-01-17 12:34:54 +11:00
psychedelicious
edff16124f feat(ui): support zipped batch nodes 2025-01-17 12:34:54 +11:00
psychedelicious
d82d990b23 feat(ui): add number range generators 2025-01-17 12:19:04 +11:00
psychedelicious
2c64b60d32 Revert "feat(ui): rough out number generators for number collection fields"
This reverts commit 41cc6f1f96bca2a51727f21bd727ca48eab669bc.
2025-01-17 12:19:04 +11:00
psychedelicious
b1c4ec0888 feat(ui): rough out number generators for number collection fields 2025-01-17 12:19:04 +11:00
psychedelicious
c1fd28472d fix(ui): float batch data creation 2025-01-17 12:19:04 +11:00
psychedelicious
bfe6d98cba feat(ui): support float batches 2025-01-17 12:19:04 +11:00
psychedelicious
c26b3cd54f refactor(ui): abstract out helper to add batch data 2025-01-17 12:19:04 +11:00
psychedelicious
c012d832d2 fix(ui): typo 2025-01-17 12:19:04 +11:00
psychedelicious
b212332b3e feat(ui): support integer batches 2025-01-17 12:19:04 +11:00
psychedelicious
b52b271dc4 feat(ui): support string batches 2025-01-17 12:19:04 +11:00