mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 10:42:44 +00:00
[Backport to rh-test] fix(telemetry): remove redundant run tracking; keep click analytics + single execution event (#6552)
## Summary
Manual backport of #6518 to the `rh-test` branch.
Deduplicates workflow run telemetry and keeps a single source of truth
for execution while retaining click analytics and attributing initiator
source.
- Keep execution tracking in one place via `trackWorkflowExecution()`
- Keep click analytics via `trackRunButton(...)`
- Attribute initiator with `trigger_source` = 'button' | 'keybinding' |
'legacy_ui'
- Remove pre-tracking from keybindings to avoid double/triple counting
- Update legacy UI buttons to emit both click + execution events
## Backport Notes
This backport required manual conflict resolution in:
- `src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue` - Added
batchCount tracking and trigger_source metadata
- `src/composables/useCoreCommands.ts` - Added error handling and
execution tracking
- `src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts`
- Updated trackRunButton signature with trigger_source support
Additionally added:
- `trackUiButtonClicked` method to TelemetryProvider interface
- `UiButtonClickMetadata` type definition
- `UI_BUTTON_CLICKED` event constant
All conflicts resolved intelligently to maintain the intent of the
original PR while adapting to the rh-test branch codebase.
## Original PR
- Original PR: #6518
- Original commit: 6fe88dba54
## Testing
- ✅ Typecheck passed
- ✅ Pre-commit hooks passed (lint, format)
- ✅ All conflicts resolved
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6552-Backport-to-rh-test-fix-telemetry-remove-redundant-run-tracking-keep-click-analytics-2a06d73d365081f78e4ad46a16be69f1)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Christian Byrne <c.byrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Christian Byrne <chrbyrne96@gmail.com>
This commit is contained in:
@@ -100,7 +100,7 @@ import BatchCountEdit from '../BatchCountEdit.vue'
|
|||||||
|
|
||||||
const workspaceStore = useWorkspaceStore()
|
const workspaceStore = useWorkspaceStore()
|
||||||
const queueCountStore = storeToRefs(useQueuePendingTaskCountStore())
|
const queueCountStore = storeToRefs(useQueuePendingTaskCountStore())
|
||||||
const { mode: queueMode } = storeToRefs(useQueueSettingsStore())
|
const { mode: queueMode, batchCount } = storeToRefs(useQueueSettingsStore())
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const queueModeMenuItemLookup = computed(() => {
|
const queueModeMenuItemLookup = computed(() => {
|
||||||
@@ -158,9 +158,18 @@ const queuePrompt = async (e: Event) => {
|
|||||||
? 'Comfy.QueuePromptFront'
|
? 'Comfy.QueuePromptFront'
|
||||||
: 'Comfy.QueuePrompt'
|
: 'Comfy.QueuePrompt'
|
||||||
|
|
||||||
useTelemetry()?.trackRunButton({ subscribe_to_run: false })
|
if (batchCount.value > 1) {
|
||||||
|
useTelemetry()?.trackUiButtonClicked({
|
||||||
|
button_id: 'queue_run_multiple_batches_submitted'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
await commandStore.execute(commandId)
|
await commandStore.execute(commandId, {
|
||||||
|
metadata: {
|
||||||
|
subscribe_to_run: false,
|
||||||
|
trigger_source: 'button'
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { useSubscription } from '@/platform/cloud/subscription/composables/useSu
|
|||||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||||
import { SUPPORT_URL } from '@/platform/support/config'
|
import { SUPPORT_URL } from '@/platform/support/config'
|
||||||
import { useTelemetry } from '@/platform/telemetry'
|
import { useTelemetry } from '@/platform/telemetry'
|
||||||
|
import type { ExecutionTriggerSource } from '@/platform/telemetry/types'
|
||||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||||
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
|
import { useWorkflowService } from '@/platform/workflow/core/services/workflowService'
|
||||||
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
||||||
@@ -465,7 +466,11 @@ export function useCoreCommands(): ComfyCommand[] {
|
|||||||
label: 'Queue Prompt',
|
label: 'Queue Prompt',
|
||||||
versionAdded: '1.3.7',
|
versionAdded: '1.3.7',
|
||||||
category: 'essentials' as const,
|
category: 'essentials' as const,
|
||||||
function: async () => {
|
function: async (metadata?: {
|
||||||
|
subscribe_to_run?: boolean
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
|
}) => {
|
||||||
|
useTelemetry()?.trackRunButton(metadata)
|
||||||
if (!isActiveSubscription.value) {
|
if (!isActiveSubscription.value) {
|
||||||
showSubscriptionDialog()
|
showSubscriptionDialog()
|
||||||
return
|
return
|
||||||
@@ -484,7 +489,11 @@ export function useCoreCommands(): ComfyCommand[] {
|
|||||||
label: 'Queue Prompt (Front)',
|
label: 'Queue Prompt (Front)',
|
||||||
versionAdded: '1.3.7',
|
versionAdded: '1.3.7',
|
||||||
category: 'essentials' as const,
|
category: 'essentials' as const,
|
||||||
function: async () => {
|
function: async (metadata?: {
|
||||||
|
subscribe_to_run?: boolean
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
|
}) => {
|
||||||
|
useTelemetry()?.trackRunButton(metadata)
|
||||||
if (!isActiveSubscription.value) {
|
if (!isActiveSubscription.value) {
|
||||||
showSubscriptionDialog()
|
showSubscriptionDialog()
|
||||||
return
|
return
|
||||||
@@ -502,7 +511,11 @@ export function useCoreCommands(): ComfyCommand[] {
|
|||||||
icon: 'pi pi-play',
|
icon: 'pi pi-play',
|
||||||
label: 'Queue Selected Output Nodes',
|
label: 'Queue Selected Output Nodes',
|
||||||
versionAdded: '1.19.6',
|
versionAdded: '1.19.6',
|
||||||
function: async () => {
|
function: async (metadata?: {
|
||||||
|
subscribe_to_run?: boolean
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
|
}) => {
|
||||||
|
useTelemetry()?.trackRunButton(metadata)
|
||||||
if (!isActiveSubscription.value) {
|
if (!isActiveSubscription.value) {
|
||||||
showSubscriptionDialog()
|
showSubscriptionDialog()
|
||||||
return
|
return
|
||||||
@@ -525,6 +538,17 @@ export function useCoreCommands(): ComfyCommand[] {
|
|||||||
// Get execution IDs for all selected output nodes and their descendants
|
// Get execution IDs for all selected output nodes and their descendants
|
||||||
const executionIds =
|
const executionIds =
|
||||||
getExecutionIdsForSelectedNodes(selectedOutputNodes)
|
getExecutionIdsForSelectedNodes(selectedOutputNodes)
|
||||||
|
|
||||||
|
if (executionIds.length === 0) {
|
||||||
|
toastStore.add({
|
||||||
|
severity: 'error',
|
||||||
|
summary: t('toastMessages.failedToQueue'),
|
||||||
|
detail: t('toastMessages.failedExecutionPathResolution'),
|
||||||
|
life: 3000
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
useTelemetry()?.trackWorkflowExecution()
|
||||||
await app.queuePrompt(0, batchCount, executionIds)
|
await app.queuePrompt(0, batchCount, executionIds)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1742,21 +1742,22 @@ const ext: ComfyExtension = {
|
|||||||
label: 'Convert selected nodes to group node',
|
label: 'Convert selected nodes to group node',
|
||||||
icon: 'pi pi-sitemap',
|
icon: 'pi pi-sitemap',
|
||||||
versionAdded: '1.3.17',
|
versionAdded: '1.3.17',
|
||||||
function: convertSelectedNodesToGroupNode
|
function: () => convertSelectedNodesToGroupNode()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Comfy.GroupNode.UngroupSelectedGroupNodes',
|
id: 'Comfy.GroupNode.UngroupSelectedGroupNodes',
|
||||||
label: 'Ungroup selected group nodes',
|
label: 'Ungroup selected group nodes',
|
||||||
icon: 'pi pi-sitemap',
|
icon: 'pi pi-sitemap',
|
||||||
versionAdded: '1.3.17',
|
versionAdded: '1.3.17',
|
||||||
function: ungroupSelectedGroupNodes
|
function: () => ungroupSelectedGroupNodes()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'Comfy.GroupNode.ManageGroupNodes',
|
id: 'Comfy.GroupNode.ManageGroupNodes',
|
||||||
label: 'Manage group nodes',
|
label: 'Manage group nodes',
|
||||||
icon: 'pi pi-cog',
|
icon: 'pi pi-cog',
|
||||||
versionAdded: '1.3.17',
|
versionAdded: '1.3.17',
|
||||||
function: manageGroupNodes
|
function: (...args: unknown[]) =>
|
||||||
|
manageGroupNodes(args[0] as string | undefined)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
keybindings: [
|
keybindings: [
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {
|
|||||||
ExecutionContext,
|
ExecutionContext,
|
||||||
ExecutionErrorMetadata,
|
ExecutionErrorMetadata,
|
||||||
ExecutionSuccessMetadata,
|
ExecutionSuccessMetadata,
|
||||||
|
ExecutionTriggerSource,
|
||||||
HelpCenterClosedMetadata,
|
HelpCenterClosedMetadata,
|
||||||
HelpCenterOpenedMetadata,
|
HelpCenterOpenedMetadata,
|
||||||
HelpResourceClickedMetadata,
|
HelpResourceClickedMetadata,
|
||||||
@@ -32,6 +33,7 @@ import type {
|
|||||||
TemplateLibraryClosedMetadata,
|
TemplateLibraryClosedMetadata,
|
||||||
TemplateLibraryMetadata,
|
TemplateLibraryMetadata,
|
||||||
TemplateMetadata,
|
TemplateMetadata,
|
||||||
|
UiButtonClickMetadata,
|
||||||
WorkflowCreatedMetadata,
|
WorkflowCreatedMetadata,
|
||||||
WorkflowImportMetadata
|
WorkflowImportMetadata
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
@@ -59,6 +61,7 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
private mixpanel: OverridedMixpanel | null = null
|
private mixpanel: OverridedMixpanel | null = null
|
||||||
private eventQueue: QueuedEvent[] = []
|
private eventQueue: QueuedEvent[] = []
|
||||||
private isInitialized = false
|
private isInitialized = false
|
||||||
|
private lastTriggerSource: ExecutionTriggerSource | undefined
|
||||||
|
|
||||||
// Onboarding mode - starts true, set to false when app is fully ready
|
// Onboarding mode - starts true, set to false when app is fully ready
|
||||||
private isOnboardingMode = true
|
private isOnboardingMode = true
|
||||||
@@ -354,7 +357,10 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
clearTopupUtil()
|
clearTopupUtil()
|
||||||
}
|
}
|
||||||
|
|
||||||
trackRunButton(options?: { subscribe_to_run?: boolean }): void {
|
trackRunButton(options?: {
|
||||||
|
subscribe_to_run?: boolean
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
|
}): void {
|
||||||
if (this.isOnboardingMode) {
|
if (this.isOnboardingMode) {
|
||||||
// During onboarding, track basic run button click without workflow context
|
// During onboarding, track basic run button click without workflow context
|
||||||
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, {
|
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, {
|
||||||
@@ -365,7 +371,8 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
total_node_count: 0,
|
total_node_count: 0,
|
||||||
subgraph_count: 0,
|
subgraph_count: 0,
|
||||||
has_api_nodes: false,
|
has_api_nodes: false,
|
||||||
api_node_names: []
|
api_node_names: [],
|
||||||
|
trigger_source: options?.trigger_source
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -380,20 +387,14 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
total_node_count: executionContext.total_node_count,
|
total_node_count: executionContext.total_node_count,
|
||||||
subgraph_count: executionContext.subgraph_count,
|
subgraph_count: executionContext.subgraph_count,
|
||||||
has_api_nodes: executionContext.has_api_nodes,
|
has_api_nodes: executionContext.has_api_nodes,
|
||||||
api_node_names: executionContext.api_node_names
|
api_node_names: executionContext.api_node_names,
|
||||||
|
trigger_source: options?.trigger_source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lastTriggerSource = options?.trigger_source
|
||||||
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, runButtonProperties)
|
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, runButtonProperties)
|
||||||
}
|
}
|
||||||
|
|
||||||
trackRunTriggeredViaKeybinding(): void {
|
|
||||||
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_KEYBINDING)
|
|
||||||
}
|
|
||||||
|
|
||||||
trackRunTriggeredViaMenu(): void {
|
|
||||||
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_MENU)
|
|
||||||
}
|
|
||||||
|
|
||||||
trackSurvey(
|
trackSurvey(
|
||||||
stage: 'opened' | 'submitted',
|
stage: 'opened' | 'submitted',
|
||||||
responses?: SurveyResponses
|
responses?: SurveyResponses
|
||||||
@@ -501,6 +502,10 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
this.trackEvent(TelemetryEvents.WORKFLOW_CREATED, metadata)
|
this.trackEvent(TelemetryEvents.WORKFLOW_CREATED, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackUiButtonClicked(metadata: UiButtonClickMetadata): void {
|
||||||
|
this.trackEvent(TelemetryEvents.UI_BUTTON_CLICKED, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
trackWorkflowExecution(): void {
|
trackWorkflowExecution(): void {
|
||||||
if (this.isOnboardingMode) {
|
if (this.isOnboardingMode) {
|
||||||
// During onboarding, track basic execution without workflow context
|
// During onboarding, track basic execution without workflow context
|
||||||
@@ -518,7 +523,12 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const context = this.getExecutionContext()
|
const context = this.getExecutionContext()
|
||||||
this.trackEvent(TelemetryEvents.EXECUTION_START, context)
|
const eventContext: ExecutionContext = {
|
||||||
|
...context,
|
||||||
|
trigger_source: this.lastTriggerSource ?? 'unknown'
|
||||||
|
}
|
||||||
|
this.trackEvent(TelemetryEvents.EXECUTION_START, eventContext)
|
||||||
|
this.lastTriggerSource = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
trackExecutionError(metadata: ExecutionErrorMetadata): void {
|
trackExecutionError(metadata: ExecutionErrorMetadata): void {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export interface RunButtonProperties {
|
|||||||
subgraph_count: number
|
subgraph_count: number
|
||||||
has_api_nodes: boolean
|
has_api_nodes: boolean
|
||||||
api_node_names: string[]
|
api_node_names: string[]
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,6 +71,7 @@ export interface ExecutionContext {
|
|||||||
total_node_count: number
|
total_node_count: number
|
||||||
has_api_nodes: boolean
|
has_api_nodes: boolean
|
||||||
api_node_names: string[]
|
api_node_names: string[]
|
||||||
|
trigger_source?: ExecutionTriggerSource
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,6 +195,14 @@ export interface TemplateFilterMetadata {
|
|||||||
total_count: number
|
total_count: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI button click tracking metadata
|
||||||
|
*/
|
||||||
|
export interface UiButtonClickMetadata {
|
||||||
|
/** Canonical identifier for the button (e.g., "comfy_logo") */
|
||||||
|
button_id: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Help center opened metadata
|
* Help center opened metadata
|
||||||
*/
|
*/
|
||||||
@@ -250,9 +260,10 @@ export interface TelemetryProvider {
|
|||||||
trackAddApiCreditButtonClicked(): void
|
trackAddApiCreditButtonClicked(): void
|
||||||
trackApiCreditTopupButtonPurchaseClicked(amount: number): void
|
trackApiCreditTopupButtonPurchaseClicked(amount: number): void
|
||||||
trackApiCreditTopupSucceeded(): void
|
trackApiCreditTopupSucceeded(): void
|
||||||
trackRunButton(options?: { subscribe_to_run?: boolean }): void
|
trackRunButton(options?: {
|
||||||
trackRunTriggeredViaKeybinding(): void
|
subscribe_to_run?: boolean
|
||||||
trackRunTriggeredViaMenu(): void
|
trigger_source?: ExecutionTriggerSource
|
||||||
|
}): void
|
||||||
|
|
||||||
// Credit top-up tracking (composition with internal utilities)
|
// Credit top-up tracking (composition with internal utilities)
|
||||||
startTopupTracking(): void
|
startTopupTracking(): void
|
||||||
@@ -284,6 +295,9 @@ export interface TelemetryProvider {
|
|||||||
// Template filter tracking events
|
// Template filter tracking events
|
||||||
trackTemplateFilterChanged(metadata: TemplateFilterMetadata): void
|
trackTemplateFilterChanged(metadata: TemplateFilterMetadata): void
|
||||||
|
|
||||||
|
// Generic UI button click events
|
||||||
|
trackUiButtonClicked(metadata: UiButtonClickMetadata): void
|
||||||
|
|
||||||
// Help center events
|
// Help center events
|
||||||
trackHelpCenterOpened(metadata: HelpCenterOpenedMetadata): void
|
trackHelpCenterOpened(metadata: HelpCenterOpenedMetadata): void
|
||||||
trackHelpResourceClicked(metadata: HelpResourceClickedMetadata): void
|
trackHelpResourceClicked(metadata: HelpResourceClickedMetadata): void
|
||||||
@@ -321,8 +335,6 @@ export const TelemetryEvents = {
|
|||||||
|
|
||||||
// Subscription Flow
|
// Subscription Flow
|
||||||
RUN_BUTTON_CLICKED: 'app:run_button_click',
|
RUN_BUTTON_CLICKED: 'app:run_button_click',
|
||||||
RUN_TRIGGERED_KEYBINDING: 'app:run_triggered_keybinding',
|
|
||||||
RUN_TRIGGERED_MENU: 'app:run_triggered_menu',
|
|
||||||
SUBSCRIPTION_REQUIRED_MODAL_OPENED: 'app:subscription_required_modal_opened',
|
SUBSCRIPTION_REQUIRED_MODAL_OPENED: 'app:subscription_required_modal_opened',
|
||||||
SUBSCRIBE_NOW_BUTTON_CLICKED: 'app:subscribe_now_button_clicked',
|
SUBSCRIBE_NOW_BUTTON_CLICKED: 'app:subscribe_now_button_clicked',
|
||||||
MONTHLY_SUBSCRIPTION_SUCCEEDED: 'app:monthly_subscription_succeeded',
|
MONTHLY_SUBSCRIPTION_SUCCEEDED: 'app:monthly_subscription_succeeded',
|
||||||
@@ -368,12 +380,21 @@ export const TelemetryEvents = {
|
|||||||
// Execution Lifecycle
|
// Execution Lifecycle
|
||||||
EXECUTION_START: 'execution_start',
|
EXECUTION_START: 'execution_start',
|
||||||
EXECUTION_ERROR: 'execution_error',
|
EXECUTION_ERROR: 'execution_error',
|
||||||
EXECUTION_SUCCESS: 'execution_success'
|
EXECUTION_SUCCESS: 'execution_success',
|
||||||
|
|
||||||
|
// Generic UI Button Click
|
||||||
|
UI_BUTTON_CLICKED: 'app:ui_button_clicked'
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type TelemetryEventName =
|
export type TelemetryEventName =
|
||||||
(typeof TelemetryEvents)[keyof typeof TelemetryEvents]
|
(typeof TelemetryEvents)[keyof typeof TelemetryEvents]
|
||||||
|
|
||||||
|
export type ExecutionTriggerSource =
|
||||||
|
| 'button'
|
||||||
|
| 'keybinding'
|
||||||
|
| 'legacy_ui'
|
||||||
|
| 'unknown'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Union type for all possible telemetry event properties
|
* Union type for all possible telemetry event properties
|
||||||
*/
|
*/
|
||||||
@@ -394,6 +415,7 @@ export type TelemetryEventProperties =
|
|||||||
| NodeSearchMetadata
|
| NodeSearchMetadata
|
||||||
| NodeSearchResultMetadata
|
| NodeSearchResultMetadata
|
||||||
| TemplateFilterMetadata
|
| TemplateFilterMetadata
|
||||||
|
| UiButtonClickMetadata
|
||||||
| HelpCenterOpenedMetadata
|
| HelpCenterOpenedMetadata
|
||||||
| HelpResourceClickedMetadata
|
| HelpResourceClickedMetadata
|
||||||
| HelpCenterClosedMetadata
|
| HelpCenterClosedMetadata
|
||||||
|
|||||||
@@ -480,7 +480,8 @@ export class ComfyUI {
|
|||||||
textContent: 'Queue Prompt',
|
textContent: 'Queue Prompt',
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
if (isCloud) {
|
if (isCloud) {
|
||||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
useTelemetry()?.trackRunButton({ trigger_source: 'legacy_ui' })
|
||||||
|
useTelemetry()?.trackWorkflowExecution()
|
||||||
}
|
}
|
||||||
app.queuePrompt(0, this.batchCount)
|
app.queuePrompt(0, this.batchCount)
|
||||||
}
|
}
|
||||||
@@ -587,7 +588,8 @@ export class ComfyUI {
|
|||||||
textContent: 'Queue Front',
|
textContent: 'Queue Front',
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
if (isCloud) {
|
if (isCloud) {
|
||||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
useTelemetry()?.trackRunButton({ trigger_source: 'legacy_ui' })
|
||||||
|
useTelemetry()?.trackWorkflowExecution()
|
||||||
}
|
}
|
||||||
app.queuePrompt(-1, this.batchCount)
|
app.queuePrompt(-1, this.batchCount)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { CORE_KEYBINDINGS } from '@/constants/coreKeybindings'
|
import { CORE_KEYBINDINGS } from '@/constants/coreKeybindings'
|
||||||
import { isCloud } from '@/platform/distribution/types'
|
|
||||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||||
import { useTelemetry } from '@/platform/telemetry'
|
|
||||||
import { app } from '@/scripts/app'
|
import { app } from '@/scripts/app'
|
||||||
import { useCommandStore } from '@/stores/commandStore'
|
import { useCommandStore } from '@/stores/commandStore'
|
||||||
import { useDialogStore } from '@/stores/dialogStore'
|
import { useDialogStore } from '@/stores/dialogStore'
|
||||||
@@ -66,15 +64,20 @@ export const useKeybindingService = () => {
|
|||||||
|
|
||||||
// Prevent default browser behavior first, then execute the command
|
// Prevent default browser behavior first, then execute the command
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
if (
|
const runCommandIds = new Set([
|
||||||
isCloud &&
|
'Comfy.QueuePrompt',
|
||||||
(keybinding.commandId === 'Comfy.QueuePrompt' ||
|
'Comfy.QueuePromptFront',
|
||||||
keybinding.commandId === 'Comfy.QueuePromptFront' ||
|
'Comfy.QueueSelectedOutputNodes'
|
||||||
keybinding.commandId === 'Comfy.QueueSelectedOutputNodes')
|
])
|
||||||
) {
|
if (runCommandIds.has(keybinding.commandId)) {
|
||||||
useTelemetry()?.trackRunTriggeredViaKeybinding()
|
await commandStore.execute(keybinding.commandId, {
|
||||||
|
metadata: {
|
||||||
|
trigger_source: 'keybinding'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await commandStore.execute(keybinding.commandId)
|
||||||
}
|
}
|
||||||
await commandStore.execute(keybinding.commandId)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type { KeybindingImpl } from './keybindingStore'
|
|||||||
|
|
||||||
export interface ComfyCommand {
|
export interface ComfyCommand {
|
||||||
id: string
|
id: string
|
||||||
function: () => void | Promise<void>
|
function: (metadata?: Record<string, unknown>) => void | Promise<void>
|
||||||
|
|
||||||
label?: string | (() => string)
|
label?: string | (() => string)
|
||||||
icon?: string | (() => string)
|
icon?: string | (() => string)
|
||||||
@@ -24,7 +24,7 @@ export interface ComfyCommand {
|
|||||||
|
|
||||||
export class ComfyCommandImpl implements ComfyCommand {
|
export class ComfyCommandImpl implements ComfyCommand {
|
||||||
id: string
|
id: string
|
||||||
function: () => void | Promise<void>
|
function: (metadata?: Record<string, unknown>) => void | Promise<void>
|
||||||
_label?: string | (() => string)
|
_label?: string | (() => string)
|
||||||
_icon?: string | (() => string)
|
_icon?: string | (() => string)
|
||||||
_tooltip?: string | (() => string)
|
_tooltip?: string | (() => string)
|
||||||
@@ -96,11 +96,17 @@ export const useCommandStore = defineStore('command', () => {
|
|||||||
const { wrapWithErrorHandlingAsync } = useErrorHandling()
|
const { wrapWithErrorHandlingAsync } = useErrorHandling()
|
||||||
const execute = async (
|
const execute = async (
|
||||||
commandId: string,
|
commandId: string,
|
||||||
errorHandler?: (error: any) => void
|
options?: {
|
||||||
|
errorHandler?: (error: unknown) => void
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
) => {
|
) => {
|
||||||
const command = getCommand(commandId)
|
const command = getCommand(commandId)
|
||||||
if (command) {
|
if (command) {
|
||||||
await wrapWithErrorHandlingAsync(command.function, errorHandler)()
|
await wrapWithErrorHandlingAsync(
|
||||||
|
() => command.function(options?.metadata),
|
||||||
|
options?.errorHandler
|
||||||
|
)()
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Command ${commandId} not found`)
|
throw new Error(`Command ${commandId} not found`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import type { MenuItem } from 'primevue/menuitem'
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { CORE_MENU_COMMANDS } from '@/constants/coreMenuCommands'
|
import { CORE_MENU_COMMANDS } from '@/constants/coreMenuCommands'
|
||||||
import { isCloud } from '@/platform/distribution/types'
|
|
||||||
import { useTelemetry } from '@/platform/telemetry'
|
|
||||||
import type { ComfyExtension } from '@/types/comfy'
|
import type { ComfyExtension } from '@/types/comfy'
|
||||||
|
|
||||||
import { useCommandStore } from './commandStore'
|
import { useCommandStore } from './commandStore'
|
||||||
@@ -64,17 +62,7 @@ export const useMenuItemStore = defineStore('menuItem', () => {
|
|||||||
.map(
|
.map(
|
||||||
(command) =>
|
(command) =>
|
||||||
({
|
({
|
||||||
command: () => {
|
command: () => commandStore.execute(command.id),
|
||||||
if (
|
|
||||||
isCloud &&
|
|
||||||
(command.id === 'Comfy.QueuePrompt' ||
|
|
||||||
command.id === 'Comfy.QueuePromptFront' ||
|
|
||||||
command.id === 'Comfy.QueueSelectedOutputNodes')
|
|
||||||
) {
|
|
||||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
|
||||||
}
|
|
||||||
return commandStore.execute(command.id)
|
|
||||||
},
|
|
||||||
label: command.menubarLabel,
|
label: command.menubarLabel,
|
||||||
icon: command.icon,
|
icon: command.icon,
|
||||||
tooltip: command.tooltip,
|
tooltip: command.tooltip,
|
||||||
|
|||||||
@@ -114,5 +114,11 @@ export interface ExtensionManager {
|
|||||||
|
|
||||||
export interface CommandManager {
|
export interface CommandManager {
|
||||||
commands: ComfyCommand[]
|
commands: ComfyCommand[]
|
||||||
execute(command: string, errorHandler?: (error: any) => void): void
|
execute(
|
||||||
|
command: string,
|
||||||
|
options?: {
|
||||||
|
errorHandler?: (error: unknown) => void
|
||||||
|
metadata?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
): void
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user