mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-13 17:10:06 +00:00
App mode - landing/arrange screens - 4 (#9026)
## Summary Updates messaging on app mode welcome pages and adds arrange view ## Screenshots (if applicable) Build app view <img width="628" height="470" alt="image" src="https://github.com/user-attachments/assets/7f648769-1380-4093-8de9-414d05303b87" /> Run view <img width="593" height="471" alt="image" src="https://github.com/user-attachments/assets/cc81cfd0-fa89-4402-82f4-6bbdd0e7e2f9" /> Arrange view <img width="1071" height="829" alt="image" src="https://github.com/user-attachments/assets/ae8666ef-dff1-4fde-929e-89479c891261" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9026-App-mode-landing-arrange-screens-4-30d6d73d365081f4b209f34834a2ce5e) by [Unito](https://www.unito.io)
This commit is contained in:
59
src/renderer/extensions/linearMode/LinearArrange.vue
Normal file
59
src/renderer/extensions/linearMode/LinearArrange.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useAppModeStore } from '@/stores/appModeStore'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const appModeStore = useAppModeStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="appModeStore.hasOutputs"
|
||||
role="article"
|
||||
data-testid="arrange-preview"
|
||||
class="flex flex-col items-center justify-center h-full w-3/4 gap-6 p-8 mx-auto"
|
||||
>
|
||||
<div
|
||||
class="border-warning-background border-2 border-dashed rounded-2xl w-full h-4/5 flex items-center justify-center flex-col p-12"
|
||||
>
|
||||
<p class="text-base-foreground font-bold mb-0">
|
||||
{{ t('linearMode.arrange.outputs') }}
|
||||
</p>
|
||||
<p>{{ t('linearMode.arrange.resultsLabel') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
role="article"
|
||||
data-testid="arrange-no-outputs"
|
||||
class="flex flex-col items-center justify-center h-full gap-6 p-8 w-lg mx-auto text-center"
|
||||
>
|
||||
<p class="m-0 text-base-foreground">
|
||||
{{ t('linearMode.arrange.noOutputs') }}
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col gap-1 text-muted-foreground w-lg text-[14px]">
|
||||
<p class="mt-0 p-0">{{ t('linearMode.arrange.switchToSelect') }}</p>
|
||||
|
||||
<i18n-t keypath="linearMode.arrange.connectAtLeastOne" tag="div">
|
||||
<template #atLeastOne>
|
||||
<span class="italic font-bold">
|
||||
{{ t('linearMode.arrange.atLeastOne') }}
|
||||
</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
|
||||
<p class="mt-0 p-0">{{ t('linearMode.arrange.outputExamples') }}</p>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
@click="appModeStore.setMode('builder:select')"
|
||||
>
|
||||
{{ t('linearMode.arrange.switchToSelectButton') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -147,7 +147,7 @@ defineExpose({ runButtonClick })
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
v-if="!appModeStore.isBuilderMode"
|
||||
v-if="!appModeStore.isBuilderMode && appModeStore.hasOutputs"
|
||||
class="flex flex-col min-w-80 md:h-full"
|
||||
>
|
||||
<section
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useWorkflowStore } from '@/platform/workflow/management/stores/workflow
|
||||
import { extractWorkflowFromAsset } from '@/platform/workflow/utils/workflowExtractionUtil'
|
||||
import ImagePreview from '@/renderer/extensions/linearMode/ImagePreview.vue'
|
||||
import LinearWelcome from '@/renderer/extensions/linearMode/LinearWelcome.vue'
|
||||
import LinearArrange from '@/renderer/extensions/linearMode/LinearArrange.vue'
|
||||
import OutputHistory from '@/renderer/extensions/linearMode/OutputHistory.vue'
|
||||
// Lazy-loaded to avoid pulling THREE.js into the main bundle
|
||||
const Preview3d = () => import('@/renderer/extensions/linearMode/Preview3d.vue')
|
||||
@@ -28,11 +29,11 @@ import type { ResultItemImpl } from '@/stores/queueStore'
|
||||
import { formatDuration } from '@/utils/dateTimeUtil'
|
||||
import { collectAllNodes } from '@/utils/graphTraversalUtil'
|
||||
import { executeWidgetsCallback } from '@/utils/litegraphUtil'
|
||||
|
||||
import { useAppModeStore } from '@/stores/appModeStore'
|
||||
const { t, d } = useI18n()
|
||||
const mediaActions = useMediaAssetActions()
|
||||
const nodeOutputStore = useNodeOutputStore()
|
||||
|
||||
const appModeStore = useAppModeStore()
|
||||
const { runButtonClick } = defineProps<{
|
||||
runButtonClick?: (e: Event) => void
|
||||
mobile?: boolean
|
||||
@@ -190,6 +191,7 @@ async function rerun(e: Event) {
|
||||
v-else-if="getMediaType(selectedOutput) === '3d'"
|
||||
:model-url="selectedOutput!.url"
|
||||
/>
|
||||
<LinearArrange v-else-if="appModeStore.mode === 'builder:arrange'" />
|
||||
<LinearWelcome v-else />
|
||||
<OutputHistory
|
||||
@update-selection="
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useAppModeStore } from '@/stores/appModeStore'
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const appModeStore = useAppModeStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -11,21 +14,50 @@ const { t } = useI18n()
|
||||
class="flex flex-col items-center justify-center h-full gap-6 p-8 max-w-lg mx-auto text-center"
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<h2 class="text-xl font-semibold text-base-foreground">
|
||||
{{ t('linearMode.welcome.title')
|
||||
}}<sup class="ml-1 text-xs font-normal text-muted-foreground">{{
|
||||
t('g.experimental')
|
||||
}}</sup>
|
||||
<h2 class="text-3xl font-semibold text-muted-foreground">
|
||||
{{ t('linearMode.welcome.title') }}
|
||||
</h2>
|
||||
<p class="text-base text-muted-foreground">
|
||||
{{ t('linearMode.welcome.intro') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3 text-xs text-muted-foreground/70 max-w-md">
|
||||
<p>{{ t('linearMode.welcome.layout') }}</p>
|
||||
<p>{{ t('linearMode.welcome.sharing') }}</p>
|
||||
<p>{{ t('linearMode.welcome.widget') }}</p>
|
||||
<div class="flex flex-col gap-3 text-muted-foreground max-w-md text-[14px]">
|
||||
<p class="mt-0">{{ t('linearMode.welcome.message') }}</p>
|
||||
<p class="mt-0">{{ t('linearMode.welcome.controls') }}</p>
|
||||
<p class="mt-0">{{ t('linearMode.welcome.sharing') }}</p>
|
||||
</div>
|
||||
<div v-if="appModeStore.hasOutputs" class="flex flex-row gap-2 text-[14px]">
|
||||
<p class="mt-0 text-base-foreground">
|
||||
<i18n-t keypath="linearMode.welcome.getStarted" tag="span">
|
||||
<template #runButton>
|
||||
<span
|
||||
class="inline-flex items-center px-3.5 py-0.5 mx-0.5 transform -translate-y-0.5 rounded bg-primary-background text-base-foreground text-xxs font-medium cursor-default"
|
||||
>
|
||||
{{ t('menu.run') }}
|
||||
</span>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="flex flex-row gap-2">
|
||||
<Button
|
||||
variant="textonly"
|
||||
size="lg"
|
||||
@click="appModeStore.setMode('graph')"
|
||||
>
|
||||
{{ t('linearMode.welcome.backToWorkflow') }}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
@click="appModeStore.setMode('builder:select')"
|
||||
>
|
||||
<i class="icon-[lucide--hammer]" />
|
||||
{{ t('linearMode.welcome.buildApp') }}
|
||||
<div
|
||||
class="bg-base-foreground text-base-background text-xxs rounded-full absolute -top-2 -right-2 px-1"
|
||||
>
|
||||
{{ t('g.experimental') }}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user