项目文件夹

文件
wehub-resource-sync 6ede33ccdb
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Has been cancelled
Build and Push Docker Images / finalize_release (push) Has been cancelled
Obsidian Plugin Lint / lint (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / compute_version (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / verify_digests (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:33:44 +08:00

118 行
3.2 KiB
TypeScript

import posthog from "posthog-js";
/**
* PostHog initialisation for the Next.js renderer.
*
* The same bundle ships in two contexts:
* 1. A normal browser session on surfsense.com -> platform = "web"
* 2. The Electron desktop app (renders the Next app from localhost)
* -> platform = "desktop"
*
* When running inside Electron we also seed `posthog-js` with the main
* process's machine distinctId so that events fired from both the renderer
* (e.g. `chat_message_sent`, page views) and the Electron main process
* (e.g. `desktop_quick_ask_opened`) share a single PostHog person before
* login, and can be merged into the authenticated user afterwards.
*/
function isElectron(): boolean {
return typeof window !== "undefined" && !!window.electronAPI;
}
function currentPlatform(): "desktop" | "web" {
return isElectron() ? "desktop" : "web";
}
async function resolveBootstrapDistinctId(): Promise<string | undefined> {
if (!isElectron() || !window.electronAPI?.getAnalyticsContext) return undefined;
try {
const ctx = await window.electronAPI.getAnalyticsContext();
return ctx?.machineId || ctx?.distinctId || undefined;
} catch {
return undefined;
}
}
async function initPostHog() {
try {
if (!process.env.NEXT_PUBLIC_POSTHOG_KEY) return;
const platform = currentPlatform();
const bootstrapDistinctId = await resolveBootstrapDistinctId();
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
api_host: "https://assets.surfsense.com",
ui_host: "https://us.posthog.com",
defaults: "2026-01-30",
capture_pageview: "history_change",
capture_pageleave: true,
...(bootstrapDistinctId
? {
bootstrap: {
distinctID: bootstrapDistinctId,
isIdentifiedID: false,
},
}
: {}),
before_send: (event) => {
if (event?.properties) {
event.properties.platform = platform;
if (platform === "desktop") {
event.properties.is_desktop = true;
}
const params = new URLSearchParams(window.location.search);
const ref = params.get("ref");
if (ref) {
event.properties.ref_code = ref;
event.properties.$set = {
...event.properties.$set,
initial_ref_code: ref,
};
event.properties.$set_once = {
...event.properties.$set_once,
first_ref_code: ref,
};
}
event.properties.$set = {
...event.properties.$set,
platform,
last_seen_at: new Date().toISOString(),
};
event.properties.$set_once = {
...event.properties.$set_once,
first_seen_platform: platform,
};
}
return event;
},
loaded: () => {
if (typeof window !== "undefined") {
// `loaded` hands back a `PostHogInterface`, but it's the same
// singleton as the default import (typed `PostHog`); use that to
// keep `window.posthog` correctly typed.
window.posthog = posthog;
}
},
});
} catch {
// PostHog init failed (likely ad-blocker) – app must continue to work
}
}
if (typeof window !== "undefined") {
window.posthog = posthog;
if ("requestIdleCallback" in window) {
requestIdleCallback(() => {
void initPostHog();
});
} else {
setTimeout(() => {
void initPostHog();
}, 3500);
}
}