mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-10 23:50:00 +00:00
## Summary Merges latest changes from `main` as of 10-06-2025. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5965-Merge-main-as-of-10-06-2025-into-rh-test-2856d73d3650812cb95fd8917278a770) by [Unito](https://www.unito.io) --------- Signed-off-by: Marcel Petrick <mail@marcelpetrick.it> Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: Benjamin Lu <benceruleanlu@proton.me> Co-authored-by: Terry Jia <terryjia88@gmail.com> Co-authored-by: snomiao <snomiao@gmail.com> Co-authored-by: Simula_r <18093452+simula-r@users.noreply.github.com> Co-authored-by: Jake Schroeder <jake.schroeder@isophex.com> Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com> Co-authored-by: AustinMroz <4284322+AustinMroz@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com> Co-authored-by: Marcel Petrick <mail@marcelpetrick.it> Co-authored-by: Alexander Brown <DrJKL0424@gmail.com> Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com> Co-authored-by: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Co-authored-by: Rizumu Ayaka <rizumu@ayaka.moe> Co-authored-by: JakeSchroeder <jake@axiom.co> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: DrJKL <DrJKL@users.noreply.github.com> Co-authored-by: ComfyUI Wiki <contact@comfyui-wiki.com>
114 lines
2.8 KiB
Vue
114 lines
2.8 KiB
Vue
<template>
|
|
<div
|
|
ref="rootEl"
|
|
class="relative overflow-hidden h-full w-full bg-neutral-900"
|
|
>
|
|
<div class="p-terminal rounded-none h-full w-full p-2">
|
|
<div ref="terminalEl" class="h-full terminal-host" />
|
|
</div>
|
|
<Button
|
|
v-tooltip.left="{
|
|
value: tooltipText,
|
|
showDelay: 300
|
|
}"
|
|
icon="pi pi-copy"
|
|
severity="secondary"
|
|
size="small"
|
|
:class="
|
|
cn('absolute top-2 right-8 transition-opacity', {
|
|
'opacity-0 pointer-events-none select-none': !isHovered
|
|
})
|
|
"
|
|
:aria-label="tooltipText"
|
|
@click="handleCopy"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useElementHover, useEventListener } from '@vueuse/core'
|
|
import type { IDisposable } from '@xterm/xterm'
|
|
import Button from 'primevue/button'
|
|
import type { Ref } from 'vue'
|
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
|
|
import { electronAPI, isElectron } from '@/utils/envUtil'
|
|
import { cn } from '@/utils/tailwindUtil'
|
|
|
|
const { t } = useI18n()
|
|
|
|
const emit = defineEmits<{
|
|
created: [ReturnType<typeof useTerminal>, Ref<HTMLElement | undefined>]
|
|
unmounted: []
|
|
}>()
|
|
const terminalEl = ref<HTMLElement | undefined>()
|
|
const rootEl = ref<HTMLElement | undefined>()
|
|
const hasSelection = ref(false)
|
|
|
|
const isHovered = useElementHover(rootEl)
|
|
|
|
const terminalData = useTerminal(terminalEl)
|
|
emit('created', terminalData, ref(rootEl))
|
|
|
|
const { terminal } = terminalData
|
|
let selectionDisposable: IDisposable | undefined
|
|
|
|
const tooltipText = computed(() => {
|
|
return hasSelection.value
|
|
? t('serverStart.copySelectionTooltip')
|
|
: t('serverStart.copyAllTooltip')
|
|
})
|
|
|
|
const handleCopy = async () => {
|
|
const existingSelection = terminal.getSelection()
|
|
const shouldSelectAll = !existingSelection
|
|
if (shouldSelectAll) terminal.selectAll()
|
|
|
|
const selectedText = shouldSelectAll
|
|
? terminal.getSelection()
|
|
: existingSelection
|
|
|
|
if (selectedText) {
|
|
await navigator.clipboard.writeText(selectedText)
|
|
|
|
if (shouldSelectAll) {
|
|
terminal.clearSelection()
|
|
}
|
|
}
|
|
}
|
|
|
|
const showContextMenu = (event: MouseEvent) => {
|
|
event.preventDefault()
|
|
electronAPI()?.showContextMenu({ type: 'text' })
|
|
}
|
|
|
|
if (isElectron()) {
|
|
useEventListener(terminalEl, 'contextmenu', showContextMenu)
|
|
}
|
|
|
|
onMounted(() => {
|
|
selectionDisposable = terminal.onSelectionChange(() => {
|
|
hasSelection.value = terminal.hasSelection()
|
|
})
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
selectionDisposable?.dispose()
|
|
emit('unmounted')
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
@reference '../../../../assets/css/style.css';
|
|
|
|
:deep(.p-terminal) .xterm {
|
|
@apply overflow-hidden;
|
|
}
|
|
|
|
:deep(.p-terminal) .xterm-screen {
|
|
@apply bg-neutral-900 overflow-hidden;
|
|
}
|
|
</style>
|