mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): add conditionally-enabled workflow publishing ui
This is a squash of a lot of scattered commits that became very difficult to clean up and make individually. Sorry. Besides the new UI, there are a number of notable changes: - Publishing logic is disabled in OSS by default. To enable it, provided a `disabledFeatures` prop _without_ "publishWorkflow". - Enqueuing a workflow is no longer handled in a redux listener. It was hard to track the state of the enqueue logic in the listener. It is now in a hook. I did not migrate the canvas and upscaling tabs - their enqueue logic is still in the listener. - When queueing a validation run, the new `useEnqueueWorkflows()` hook will update the payload with the required data for the run. - Some logic is added to the socket event listeners to handle workflow publish runs completing. - The workflow library side nav has a new "published" view. It is hidden when the "publishWorkflow" feature is disabled. - I've added `Safe` and `OrThrow` versions of some workflows hooks. These hooks typically retrieve some data from redux. For example, a node. The `Safe` hooks return the node or null if it cannot be found, while the `OrThrow` hooks return the node or raise if it cannot be found. The `OrThrow` hooks should be used within one of the gate components. These components use the `Safe` hooks and render a fallback if e.g. the node isn't found. This change is required for some of the publish flow UI. - Add support for locking the workflow editor. When locked, you can pan and zoom but that's it. Currently, it is only locked during publish flow and if a published workflow is opened.
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
import type { DynamicPromptsState } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { getShouldProcessPrompt } from 'features/dynamicPrompts/util/getShouldProcessPrompt';
|
||||
import { $isInPublishFlow } from 'features/nodes/components/sidePanel/workflow/publish';
|
||||
import { $templates } from 'features/nodes/store/nodesSlice';
|
||||
import { selectNodesSlice } from 'features/nodes/store/selectors';
|
||||
import type { NodesState, Templates } from 'features/nodes/store/types';
|
||||
@@ -84,7 +85,8 @@ const debouncedUpdateReasons = debounce(
|
||||
templates: Templates,
|
||||
upscale: UpscaleState,
|
||||
config: AppConfig,
|
||||
store: AppStore
|
||||
store: AppStore,
|
||||
isInPublishFlow: boolean
|
||||
) => {
|
||||
if (tab === 'canvas') {
|
||||
const model = selectMainModelConfig(store.getState());
|
||||
@@ -108,6 +110,7 @@ const debouncedUpdateReasons = debounce(
|
||||
workflowSettingsState: workflowSettings,
|
||||
isConnected,
|
||||
templates,
|
||||
isInPublishFlow,
|
||||
});
|
||||
$reasonsWhyCannotEnqueue.set(reasons);
|
||||
} else if (tab === 'upscaling') {
|
||||
@@ -144,6 +147,7 @@ export const useReadinessWatcher = () => {
|
||||
const canvasIsRasterizing = useStore(canvasManager?.stateApi.$isRasterizing ?? $true);
|
||||
const canvasIsSelectingObject = useStore(canvasManager?.stateApi.$isSegmenting ?? $true);
|
||||
const canvasIsCompositing = useStore(canvasManager?.compositor.$isBusy ?? $true);
|
||||
const isInPublishFlow = useStore($isInPublishFlow);
|
||||
|
||||
useEffect(() => {
|
||||
debouncedUpdateReasons(
|
||||
@@ -162,7 +166,8 @@ export const useReadinessWatcher = () => {
|
||||
templates,
|
||||
upscale,
|
||||
config,
|
||||
store
|
||||
store,
|
||||
isInPublishFlow
|
||||
);
|
||||
}, [
|
||||
store,
|
||||
@@ -181,6 +186,7 @@ export const useReadinessWatcher = () => {
|
||||
templates,
|
||||
upscale,
|
||||
workflowSettings,
|
||||
isInPublishFlow,
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -192,15 +198,16 @@ const getReasonsWhyCannotEnqueueWorkflowsTab = async (arg: {
|
||||
workflowSettingsState: WorkflowSettingsState;
|
||||
isConnected: boolean;
|
||||
templates: Templates;
|
||||
isInPublishFlow: boolean;
|
||||
}): Promise<Reason[]> => {
|
||||
const { dispatch, nodesState, workflowSettingsState, isConnected, templates } = arg;
|
||||
const { dispatch, nodesState, workflowSettingsState, isConnected, templates, isInPublishFlow } = arg;
|
||||
const reasons: Reason[] = [];
|
||||
|
||||
if (!isConnected) {
|
||||
reasons.push(disconnectedReason(i18n.t));
|
||||
}
|
||||
|
||||
if (workflowSettingsState.shouldValidateGraph) {
|
||||
if (workflowSettingsState.shouldValidateGraph || isInPublishFlow) {
|
||||
const { nodes, edges } = nodesState;
|
||||
const invocationNodes = nodes.filter(isInvocationNode);
|
||||
const batchNodes = invocationNodes.filter(isBatchNode);
|
||||
|
||||
Reference in New Issue
Block a user