mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-01 22:09:55 +00:00
WIP mobile layout for linear
This commit is contained in:
@@ -23,6 +23,7 @@ import { collectAllNodes } from '@/utils/graphTraversalUtil'
|
||||
import { executeWidgetsCallback } from '@/utils/litegraphUtil'
|
||||
|
||||
const mediaActions = useMediaAssetActions()
|
||||
const mobile = true
|
||||
|
||||
const { runButtonClick, selectedItem, selectedOutput } = defineProps<{
|
||||
latentPreview?: string
|
||||
@@ -153,8 +154,14 @@ async function rerun(e: Event) {
|
||||
]"
|
||||
/>
|
||||
</linear-output-info>
|
||||
<div
|
||||
v-if="getMediaType(selectedOutput) === 'images' && mobile"
|
||||
class="aspect-square w-full flex"
|
||||
>
|
||||
<img :src="latentPreview ?? selectedOutput!.url" />
|
||||
</div>
|
||||
<ImagePreview
|
||||
v-if="getMediaType(selectedOutput) === 'images'"
|
||||
v-else-if="getMediaType(selectedOutput) === 'images'"
|
||||
:src="latentPreview ?? selectedOutput!.url"
|
||||
/>
|
||||
<VideoPreview
|
||||
|
||||
@@ -136,7 +136,7 @@ async function runButtonClick(e: Event) {
|
||||
defineExpose({ runButtonClick })
|
||||
</script>
|
||||
<template>
|
||||
<div class="flex flex-col min-w-80 h-full">
|
||||
<div>
|
||||
<linear-workflow-info
|
||||
class="h-12 border-x border-border-subtle py-2 px-4 gap-2 bg-comfy-menu-bg flex items-center"
|
||||
>
|
||||
@@ -155,9 +155,9 @@ defineExpose({ runButtonClick })
|
||||
<Button v-if="false"> {{ t('menuLabels.publish') }} </Button>
|
||||
</linear-workflow-info>
|
||||
<div
|
||||
class="border gap-2 h-full border-[var(--interface-stroke)] bg-comfy-menu-bg flex flex-col px-2"
|
||||
class="border gap-2 border-[var(--interface-stroke)] bg-comfy-menu-bg px-2"
|
||||
>
|
||||
<linear-widgets class="grow-1 overflow-y-auto contain-size">
|
||||
<linear-widgets>
|
||||
<template v-for="(nodeData, index) of nodeDatas" :key="nodeData.id">
|
||||
<div
|
||||
v-if="index !== 0"
|
||||
|
||||
@@ -33,6 +33,7 @@ void outputs.fetchMediaList()
|
||||
|
||||
defineProps<{
|
||||
scrollResetButtonTo: string | HTMLElement
|
||||
horizontal?: boolean
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
(
|
||||
@@ -179,12 +180,14 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
cn(
|
||||
'min-w-38 flex bg-comfy-menu-bg h-full',
|
||||
settingStore.get('Comfy.Sidebar.Location') === 'right' &&
|
||||
'flex-row-reverse'
|
||||
'flex-row-reverse',
|
||||
horizontal && 'h-30'
|
||||
)
|
||||
"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<div
|
||||
v-if="!horizontal"
|
||||
class="h-full flex flex-col w-14 shrink-0 overflow-hidden items-center p-2 border-r border-node-component-border"
|
||||
>
|
||||
<SidebarIcon
|
||||
@@ -217,18 +220,23 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
<linear-outputs
|
||||
v-else
|
||||
ref="outputsRef"
|
||||
class="h-full min-w-24 grow-1 p-3 overflow-y-auto border-r-1 border-node-component-border flex flex-col items-center contain-size"
|
||||
:class="
|
||||
cn(
|
||||
'min-w-24 grow-1 p-3 border-r-1 border-node-component-border flex items-center contain-size',
|
||||
horizontal ? 'overflow-x-auto' : 'flex-col overflow-y-auto w-full'
|
||||
)
|
||||
"
|
||||
>
|
||||
<linear-job
|
||||
v-if="queueStore.runningTasks.length > 0"
|
||||
class="py-3 w-full aspect-square px-1 relative"
|
||||
class="py-3 aspect-square px-1 relative"
|
||||
>
|
||||
<ProgressSpinner class="size-full" />
|
||||
<div
|
||||
v-if="
|
||||
queueStore.runningTasks.length + queueStore.pendingTasks.length > 1
|
||||
"
|
||||
class="absolute top-0 right-0 p-1 min-w-5 h-5 flex justify-center items-center rounded-full bg-primary-background text-text-primary"
|
||||
class="absolute top-0 right-0 p-1 min-w-5 h-5 justify-center items-center rounded-full bg-primary-background text-text-primary"
|
||||
v-text="
|
||||
queueStore.runningTasks.length + queueStore.pendingTasks.length
|
||||
"
|
||||
@@ -237,7 +245,14 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
<linear-job
|
||||
v-for="(item, index) in filteredOutputs"
|
||||
:key="index"
|
||||
class="py-3 border-border-subtle flex flex-col w-full px-1 first:border-t-0 border-t-2"
|
||||
:class="
|
||||
cn(
|
||||
'border-border-subtle flex',
|
||||
horizontal
|
||||
? 'h-full px-3 py-1 first:border-l-0 border-l-2'
|
||||
: 'flex-col w-full py-3 px-1 first:border-t-0 border-t-2'
|
||||
)
|
||||
"
|
||||
>
|
||||
<template v-for="(output, key) in allOutputs(item)" :key>
|
||||
<img
|
||||
@@ -274,7 +289,10 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
</linear-job>
|
||||
</linear-outputs>
|
||||
</div>
|
||||
<teleport v-if="outputScrollState" :to="scrollResetButtonTo">
|
||||
<teleport
|
||||
v-if="outputScrollState && scrollResetButtonTo"
|
||||
:to="scrollResetButtonTo"
|
||||
>
|
||||
<Button
|
||||
:class="
|
||||
cn(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { whenever } from '@vueuse/core'
|
||||
import { breakpointsTailwind, useBreakpoints, whenever } from '@vueuse/core'
|
||||
import Splitter from 'primevue/splitter'
|
||||
import SplitterPanel from 'primevue/splitterpanel'
|
||||
import { ref, useTemplateRef } from 'vue'
|
||||
@@ -17,6 +17,8 @@ import type { ResultItemImpl } from '@/stores/queueStore'
|
||||
const nodeOutputStore = useNodeOutputStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const mobileDisplay = useBreakpoints(breakpointsTailwind).smaller('md')
|
||||
|
||||
const hasPreview = ref(false)
|
||||
whenever(
|
||||
() => nodeOutputStore.latestPreview[0],
|
||||
@@ -38,7 +40,41 @@ const linearWorkflowRef = useTemplateRef('linearWorkflowRef')
|
||||
<TopbarBadges />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="mobileDisplay"
|
||||
class="overflow-y-auto contain-size w-full h-full"
|
||||
>
|
||||
<OutputHistory
|
||||
ref="outputHistoryRef"
|
||||
scroll-reset-button-to="#linearDockBottomLeft"
|
||||
horizontal
|
||||
@update-selection="
|
||||
(e) => {
|
||||
;[selectedItem, selectedOutput, selectedIndex] = e
|
||||
hasPreview = false
|
||||
}
|
||||
"
|
||||
/>
|
||||
<LinearPreview
|
||||
:latent-preview="
|
||||
selectedIndex[0] === 0 && selectedIndex[1] === 0 && hasPreview
|
||||
? nodeOutputStore.latestPreview[0]
|
||||
: undefined
|
||||
"
|
||||
:run-button-click="linearWorkflowRef?.runButtonClick"
|
||||
:selected-item
|
||||
:selected-output
|
||||
/>
|
||||
<div id="linearDockMobileNotes" class="sticky top-4 z-20" />
|
||||
<LinearWorkflow
|
||||
ref="linearWorkflowRef"
|
||||
toast-to="#linearDockMobileToast"
|
||||
notes-to="linearDockMobileNotes"
|
||||
/>
|
||||
<div id="linearDockMobileToast" class="absolute bottom-20 z-20" />
|
||||
</div>
|
||||
<Splitter
|
||||
v-else
|
||||
class="h-[calc(100%-38px)] w-full bg-comfy-menu-secondary-bg"
|
||||
:pt="{ gutter: { class: 'bg-transparent w-4 -mx-3' } }"
|
||||
@resizestart="({ originalEvent }) => originalEvent.preventDefault()"
|
||||
|
||||
Reference in New Issue
Block a user