diff --git a/packages/common/infra/src/livedata/livedata.ts b/packages/common/infra/src/livedata/livedata.ts index d6cf7495a1..b3ddb5d38e 100644 --- a/packages/common/infra/src/livedata/livedata.ts +++ b/packages/common/infra/src/livedata/livedata.ts @@ -577,8 +577,8 @@ export type LiveDataOperation = 'set' | 'get' | 'watch' | 'unwatch'; export type Unwrap = T extends LiveData ? Unwrap - : T extends LiveData[] - ? Unwrap[] + : T extends readonly [...infer Elements] + ? { [K in keyof Elements]: Unwrap } : T; export type Flat = T extends LiveData ? LiveData> : T; diff --git a/packages/frontend/core/src/modules/telemetry/services/telemetry.ts b/packages/frontend/core/src/modules/telemetry/services/telemetry.ts index 3a111fe8a8..18cf240c65 100644 --- a/packages/frontend/core/src/modules/telemetry/services/telemetry.ts +++ b/packages/frontend/core/src/modules/telemetry/services/telemetry.ts @@ -1,3 +1,5 @@ +import { shallowEqual } from '@affine/component'; +import { ServerDeploymentType } from '@affine/graphql'; import { mixpanel } from '@affine/track'; import { LiveData, OnEvent, Service } from '@toeverything/infra'; @@ -16,8 +18,21 @@ export class TelemetryService extends Service { : new LiveData(undefined) ) .flat() - .selector(server => server?.account$) - .flat(); + .selector( + server => + [ + server?.account$, + server?.config$.selector( + c => c.type === ServerDeploymentType.Selfhosted + ), + ] as const + ) + .flat() + .map(([account, selfHosted]) => ({ + account, + selfHosted, + })) + .distinctUntilChanged(shallowEqual); constructor( private readonly globalContextService: GlobalContextService, @@ -28,20 +43,30 @@ export class TelemetryService extends Service { // TODO: support multiple servers let prevAccount: AuthAccountInfo | null = null; - const unsubscribe = this.currentAccount$.subscribe(account => { - if (prevAccount) { - mixpanel.reset(); + let prevSelfHosted: boolean | undefined = undefined; + const unsubscribe = this.currentAccount$.subscribe( + ({ account, selfHosted }) => { + if (prevAccount) { + mixpanel.reset(); + } + // the isSelfHosted property from environment is not reliable + if (selfHosted !== prevSelfHosted) { + mixpanel.register({ + isSelfHosted: selfHosted, + }); + } + prevSelfHosted = selfHosted; + prevAccount = account ?? null; + if (account) { + mixpanel.identify(account.id); + mixpanel.people.set({ + $email: account.email, + $name: account.label, + $avatar: account.avatar, + }); + } } - prevAccount = account ?? null; - if (account) { - mixpanel.identify(account.id); - mixpanel.people.set({ - $email: account.email, - $name: account.label, - $avatar: account.avatar, - }); - } - }); + ); this.disposableFns.push(() => { unsubscribe.unsubscribe(); }); diff --git a/packages/frontend/track/src/mixpanel.ts b/packages/frontend/track/src/mixpanel.ts index 507d0e885c..c6458b93ea 100644 --- a/packages/frontend/track/src/mixpanel.ts +++ b/packages/frontend/track/src/mixpanel.ts @@ -1,5 +1,5 @@ import { DebugLogger } from '@affine/debug'; -import type { OverridedMixpanel } from 'mixpanel-browser'; +import type { Dict, OverridedMixpanel } from 'mixpanel-browser'; import mixpanelBrowser from 'mixpanel-browser'; const logger = new DebugLogger('mixpanel'); @@ -30,14 +30,19 @@ function createMixpanel() { const wrapped = { init() { - mixpanel.register({ + const defaultProps = { appVersion: BUILD_CONFIG.appVersion, environment: BUILD_CONFIG.appBuildType, editorVersion: BUILD_CONFIG.editorVersion, isDesktop: BUILD_CONFIG.isElectron, - isSelfHosted: environment.isSelfHosted, distribution: BUILD_CONFIG.distribution, - }); + }; + this.register(defaultProps); + }, + // provide a way to override the default properties + register(props: Dict) { + logger.debug('register with', props); + mixpanel.register(props); }, reset() { mixpanel.reset();