Skip to content

Commit 5ca4ee3

Browse files
[merge] resolve conflicts with main branch
Merged latest changes from main into round-pigeon branch, resolving conflicts in telemetry tracking code: - ErrorDialogContent.vue: Keep specialized trackHelpResourceClicked for help/support actions instead of generic trackUiButtonClicked - CreditsPanel.vue: Add missing useSubscription import from main - MixpanelTelemetryProvider.ts: Include both UiButtonClickMetadata and WorkflowCreatedMetadata imports - types.ts: Merge all interface definitions and union types from both branches (UiButtonClickMetadata + help center + workflow metadata) Approach: Maintain separate tracking systems - use generic UI button tracking for simple interactions and specialized help/workflow tracking for domain-specific events with rich metadata. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
2 parents c77c0f0 + de53526 commit 5ca4ee3

File tree

21 files changed

+336
-28
lines changed

21 files changed

+336
-28
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,6 @@ storybook-static
9292
.github/instructions/nx.instructions.md
9393
vite.config.*.timestamp*
9494
vitest.config.*.timestamp*
95+
96+
# Weekly docs check output
97+
/output.txt

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ onlyBuiltDependencies:
112112
- '@playwright/browser-chromium'
113113
- '@playwright/browser-firefox'
114114
- '@playwright/browser-webkit'
115+
- '@sentry/cli'
115116
- '@tailwindcss/oxide'
116117
- esbuild
117118
- nx

src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,7 @@ const queuePrompt = async (e: Event) => {
160160
? 'Comfy.QueuePromptFront'
161161
: 'Comfy.QueuePrompt'
162162
163-
if (isCloud) {
164-
useTelemetry()?.trackRunButton({ subscribe_to_run: false })
165-
}
163+
useTelemetry()?.trackRunButton({ subscribe_to_run: false })
166164
167165
if (batchCount.value > 1) {
168166
useTelemetry()?.trackUiButtonClicked({ button_id: 'queue_multiple' })

src/components/dialog/content/ErrorDialogContent.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ const showReport = () => {
9797
const toast = useToast()
9898
const { t } = useI18n()
9999
const systemStatsStore = useSystemStatsStore()
100+
const telemetry = useTelemetry()
100101
101102
const title = computed<string>(
102103
() => error.nodeType ?? error.exceptionType ?? t('errorDialog.defaultTitle')
@@ -106,7 +107,11 @@ const title = computed<string>(
106107
* Open contact support flow from error dialog and track telemetry.
107108
*/
108109
const showContactSupport = async () => {
109-
useTelemetry()?.trackUiButtonClicked({ button_id: 'error_help_fix_this' })
110+
telemetry?.trackHelpResourceClicked({
111+
resource_type: 'help_feedback',
112+
is_external: true,
113+
source: 'error_dialog'
114+
})
110115
await useCommandStore().execute('Comfy.ContactSupport')
111116
}
112117

src/components/dialog/content/setting/CreditsPanel.vue

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<UserCredit text-class="text-3xl font-bold" />
1616
<Skeleton v-if="loading" width="2rem" height="2rem" />
1717
<Button
18-
v-else
18+
v-else-if="isActiveSubscription"
1919
:label="$t('credits.purchaseCredits')"
2020
:loading="loading"
2121
@click="handlePurchaseCreditsClick"
@@ -92,6 +92,13 @@
9292
icon="pi pi-question-circle"
9393
@click="handleFaqClick"
9494
/>
95+
<Button
96+
:label="$t('subscription.partnerNodesCredits')"
97+
text
98+
severity="secondary"
99+
icon="pi pi-question-circle"
100+
@click="handleOpenPartnerNodesInfo"
101+
/>
95102
<Button
96103
:label="$t('credits.messageSupport')"
97104
text
@@ -116,6 +123,7 @@ import { computed, ref, watch } from 'vue'
116123
import UserCredit from '@/components/common/UserCredit.vue'
117124
import UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue'
118125
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
126+
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
119127
import { useTelemetry } from '@/platform/telemetry'
120128
import { useDialogService } from '@/services/dialogService'
121129
import { useCommandStore } from '@/stores/commandStore'
@@ -133,6 +141,8 @@ const dialogService = useDialogService()
133141
const authStore = useFirebaseAuthStore()
134142
const authActions = useFirebaseAuthActions()
135143
const commandStore = useCommandStore()
144+
const telemetry = useTelemetry()
145+
const { isActiveSubscription } = useSubscription()
136146
const loading = computed(() => authStore.loading)
137147
const balanceLoading = computed(() => authStore.isFetchingBalance)
138148
@@ -164,12 +174,24 @@ const handleCreditsHistoryClick = async () => {
164174
}
165175
166176
const handleMessageSupport = async () => {
177+
telemetry?.trackHelpResourceClicked({
178+
resource_type: 'help_feedback',
179+
is_external: true,
180+
source: 'credits_panel'
181+
})
167182
await commandStore.execute('Comfy.ContactSupport')
168183
}
169184
170185
const handleFaqClick = () => {
171186
window.open('https://docs.comfy.org/tutorials/api-nodes/faq', '_blank')
172187
}
173188
189+
const handleOpenPartnerNodesInfo = () => {
190+
window.open(
191+
'https://docs.comfy.org/tutorials/api-nodes/overview#api-nodes',
192+
'_blank'
193+
)
194+
}
195+
174196
const creditHistory = ref<CreditHistoryItemData[]>([])
175197
</script>

src/components/graph/widgets/TextPreviewWidget.vue

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,33 @@ const props = defineProps<{
2727
2828
const executionStore = useExecutionStore()
2929
const isParentNodeExecuting = ref(true)
30-
const formattedText = computed(() => nl2br(linkifyHtml(modelValue.value)))
30+
const formattedText = computed(() => {
31+
const src = modelValue.value
32+
// Turn [[label|url]] into placeholders to avoid interfering with linkifyHtml
33+
const tokens: { label: string; url: string }[] = []
34+
const holed = src.replace(
35+
/\[\[([^|\]]+)\|([^\]]+)\]\]/g,
36+
(_m, label, url) => {
37+
tokens.push({ label: String(label), url: String(url) })
38+
return `__LNK${tokens.length - 1}__`
39+
}
40+
)
41+
42+
// Keep current behavior (auto-link bare URLs + \n -> <br>)
43+
let html = nl2br(linkifyHtml(holed))
44+
45+
// Restore placeholders as <a>...</a> (minimal escaping + http default)
46+
html = html.replace(/__LNK(\d+)__/g, (_m, i) => {
47+
const { label, url } = tokens[+i]
48+
const safeHref = url.replace(/"/g, '&quot;')
49+
const safeLabel = label.replace(/</g, '&lt;').replace(/>/g, '&gt;')
50+
return /^https?:\/\//i.test(url)
51+
? `<a href="${safeHref}" target="_blank" rel="noopener noreferrer">${safeLabel}</a>`
52+
: safeLabel
53+
})
54+
55+
return html
56+
})
3157
3258
let parentNodeId: NodeId | null = null
3359
onMounted(() => {

src/components/helpcenter/HelpCenterMenuContent.vue

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,14 @@
138138

139139
<script setup lang="ts">
140140
import Button from 'primevue/button'
141-
import { computed, nextTick, onMounted, ref } from 'vue'
141+
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
142142
import type { CSSProperties, Component } from 'vue'
143143
import { useI18n } from 'vue-i18n'
144144
145145
import PuzzleIcon from '@/components/icons/PuzzleIcon.vue'
146146
import { isCloud } from '@/platform/distribution/types'
147147
import { useSettingStore } from '@/platform/settings/settingStore'
148+
import { useTelemetry } from '@/platform/telemetry'
148149
import type { ReleaseNote } from '@/platform/updates/common/releaseService'
149150
import { useReleaseStore } from '@/platform/updates/common/releaseStore'
150151
import { useCommandStore } from '@/stores/commandStore'
@@ -196,6 +197,7 @@ const { t, locale } = useI18n()
196197
const releaseStore = useReleaseStore()
197198
const commandStore = useCommandStore()
198199
const settingStore = useSettingStore()
200+
const telemetry = useTelemetry()
199201
200202
// Emits
201203
const emit = defineEmits<{
@@ -207,6 +209,7 @@ const isSubmenuVisible = ref(false)
207209
const submenuRef = ref<HTMLElement | null>(null)
208210
const submenuStyle = ref<CSSProperties>({})
209211
let hoverTimeout: number | null = null
212+
const openedAt = ref<number>(Date.now())
210213
211214
// Computed
212215
const hasReleases = computed(() => releaseStore.releases.length > 0)
@@ -226,6 +229,7 @@ const moreItems = computed<MenuItem[]>(() => {
226229
label: t('helpCenter.desktopUserGuide'),
227230
visible: isElectron(),
228231
action: () => {
232+
trackResourceClick('docs', true)
229233
const docsUrl =
230234
electronAPI().getPlatform() === 'darwin'
231235
? EXTERNAL_LINKS.DESKTOP_GUIDE_MACOS
@@ -281,6 +285,7 @@ const menuItems = computed<MenuItem[]>(() => {
281285
icon: 'pi pi-book',
282286
label: t('helpCenter.docs'),
283287
action: () => {
288+
trackResourceClick('docs', true)
284289
openExternalLink(EXTERNAL_LINKS.DOCS)
285290
emit('close')
286291
}
@@ -291,6 +296,7 @@ const menuItems = computed<MenuItem[]>(() => {
291296
icon: 'pi pi-discord',
292297
label: 'Discord',
293298
action: () => {
299+
trackResourceClick('discord', true)
294300
openExternalLink(EXTERNAL_LINKS.DISCORD)
295301
emit('close')
296302
}
@@ -301,6 +307,7 @@ const menuItems = computed<MenuItem[]>(() => {
301307
icon: 'pi pi-github',
302308
label: t('helpCenter.github'),
303309
action: () => {
310+
trackResourceClick('github', true)
304311
openExternalLink(EXTERNAL_LINKS.GITHUB)
305312
emit('close')
306313
}
@@ -311,6 +318,7 @@ const menuItems = computed<MenuItem[]>(() => {
311318
icon: 'pi pi-question-circle',
312319
label: t('helpCenter.helpFeedback'),
313320
action: () => {
321+
trackResourceClick('help_feedback', false)
314322
void commandStore.execute('Comfy.ContactSupport')
315323
emit('close')
316324
}
@@ -326,6 +334,7 @@ const menuItems = computed<MenuItem[]>(() => {
326334
label: t('helpCenter.managerExtension'),
327335
showRedDot: shouldShowManagerRedDot.value,
328336
action: async () => {
337+
trackResourceClick('manager', false)
329338
await useManagerState().openManager({
330339
initialTab: ManagerTab.All,
331340
showToastOnLegacyError: false
@@ -349,6 +358,23 @@ const menuItems = computed<MenuItem[]>(() => {
349358
})
350359
351360
// Utility Functions
361+
const trackResourceClick = (
362+
resourceType:
363+
| 'docs'
364+
| 'discord'
365+
| 'github'
366+
| 'help_feedback'
367+
| 'manager'
368+
| 'release_notes',
369+
isExternal: boolean
370+
): void => {
371+
telemetry?.trackHelpResourceClicked({
372+
resource_type: resourceType,
373+
is_external: isExternal,
374+
source: 'help_center'
375+
})
376+
}
377+
352378
const openExternalLink = (url: string): void => {
353379
window.open(url, '_blank', 'noopener,noreferrer')
354380
}
@@ -504,6 +530,7 @@ const onReinstall = (): void => {
504530
}
505531
506532
const onReleaseClick = (release: ReleaseNote): void => {
533+
trackResourceClick('release_notes', true)
507534
void releaseStore.handleShowChangelog(release.version)
508535
const versionAnchor = formatVersionAnchor(release.version)
509536
const changelogUrl = `${getChangelogUrl()}#${versionAnchor}`
@@ -512,6 +539,7 @@ const onReleaseClick = (release: ReleaseNote): void => {
512539
}
513540
514541
const onUpdate = (_: ReleaseNote): void => {
542+
trackResourceClick('docs', true)
515543
openExternalLink(EXTERNAL_LINKS.UPDATE_GUIDE)
516544
emit('close')
517545
}
@@ -526,10 +554,16 @@ const getChangelogUrl = (): string => {
526554
527555
// Lifecycle
528556
onMounted(async () => {
557+
telemetry?.trackHelpCenterOpened({ source: 'sidebar' })
529558
if (!hasReleases.value) {
530559
await releaseStore.fetchReleases()
531560
}
532561
})
562+
563+
onBeforeUnmount(() => {
564+
const timeSpentSeconds = Math.round((Date.now() - openedAt.value) / 1000)
565+
telemetry?.trackHelpCenterClosed({ time_spent_seconds: timeSpentSeconds })
566+
})
533567
</script>
534568

535569
<style scoped>

src/composables/auth/useFirebaseAuthActions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useErrorHandling } from '@/composables/useErrorHandling'
77
import type { ErrorRecoveryStrategy } from '@/composables/useErrorHandling'
88
import { t } from '@/i18n'
99
import { isCloud } from '@/platform/distribution/types'
10+
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
1011
import { useToastStore } from '@/platform/updates/common/toastStore'
1112
import { useDialogService } from '@/services/dialogService'
1213
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
@@ -82,6 +83,9 @@ export const useFirebaseAuthActions = () => {
8283
)
8384

8485
const purchaseCredits = wrapWithErrorHandlingAsync(async (amount: number) => {
86+
const { isActiveSubscription } = useSubscription()
87+
if (!isActiveSubscription.value) return
88+
8589
const response = await authStore.initiateCreditPurchase({
8690
amount_micros: usdToMicros(amount),
8791
currency: 'usd'

0 commit comments

Comments
 (0)