Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions apps/twig/src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { LoginTransition } from "@components/LoginTransition";
import { MainLayout } from "@components/MainLayout";
import { AuthScreen } from "@features/auth/components/AuthScreen";
import { useAuthStore } from "@features/auth/stores/authStore";
import { OnboardingFlow } from "@features/onboarding/components/OnboardingFlow";
import { useWorkspaceStore } from "@features/workspace/stores/workspaceStore";
import { Flex, Spinner, Text } from "@radix-ui/themes";
import { initializePostHog } from "@renderer/lib/analytics";
Expand All @@ -18,11 +19,11 @@ import { useEffect, useRef, useState } from "react";
const log = logger.scope("app");

function App() {
const { isAuthenticated, initializeOAuth } = useAuthStore();
const { isAuthenticated, hasCompletedOnboarding } = useAuthStore();
const isDarkMode = useThemeStore((state) => state.isDarkMode);
const [isLoading, setIsLoading] = useState(true);
const [showTransition, setShowTransition] = useState(false);
const wasAuthenticated = useRef(isAuthenticated);
const wasInMainApp = useRef(isAuthenticated && hasCompletedOnboarding);

// Initialize PostHog analytics
useEffect(() => {
Expand Down Expand Up @@ -125,18 +126,28 @@ function App() {
},
});

// Wait for authStore to hydrate, then restore session from stored tokens
useEffect(() => {
initializeOAuth().finally(() => setIsLoading(false));
}, [initializeOAuth]);
const initialize = async () => {
if (!useAuthStore.persist.hasHydrated()) {
await new Promise<void>((resolve) => {
useAuthStore.persist.onFinishHydration(() => resolve());
});
}
await useAuthStore.getState().initializeOAuth();
setIsLoading(false);
};
initialize();
}, []);

// Handle auth state change for transition
// Handle transition into main app (from onboarding completion)
useEffect(() => {
if (!wasAuthenticated.current && isAuthenticated) {
// User just logged in - trigger transition
const isInMainApp = isAuthenticated && hasCompletedOnboarding;
if (!wasInMainApp.current && isInMainApp) {
setShowTransition(true);
}
wasAuthenticated.current = isAuthenticated;
}, [isAuthenticated]);
wasInMainApp.current = isInMainApp;
}, [isAuthenticated, hasCompletedOnboarding]);

const handleTransitionComplete = () => {
setShowTransition(false);
Expand All @@ -153,7 +164,7 @@ function App() {
);
}

// Determine which screen to show
// Three-phase rendering: auth → onboarding → main app
const renderContent = () => {
if (!isAuthenticated) {
return (
Expand All @@ -168,6 +179,20 @@ function App() {
);
}

if (!hasCompletedOnboarding) {
return (
<motion.div
key="onboarding"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
>
<OnboardingFlow />
</motion.div>
);
}

return (
<motion.div
key="main"
Expand Down
41 changes: 26 additions & 15 deletions apps/twig/src/renderer/api/posthogClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,17 @@ export class PostHogAPIClient {

async getIntegrations() {
const teamId = await this.getTeamId();
return this.getIntegrationsForProject(teamId);
}

async getIntegrationsForProject(projectId: number) {
const url = new URL(
`${this.api.baseUrl}/api/environments/${teamId}/integrations/`,
`${this.api.baseUrl}/api/environments/${projectId}/integrations/`,
);
const response = await this.api.fetcher.fetch({
method: "get",
url,
path: `/api/environments/${teamId}/integrations/`,
path: `/api/environments/${projectId}/integrations/`,
});

if (!response.ok) {
Expand Down Expand Up @@ -584,29 +588,36 @@ export class PostHogAPIClient {
}

/**
* Get all organizations the user belongs to.
* Get billing information for a specific organization.
*/
async getOrganizations(): Promise<
Array<{ id: string; name: string; slug: string }>
> {
const url = new URL(`${this.api.baseUrl}/api/organizations/`);
async getOrgBilling(orgId: string): Promise<{
has_active_subscription: boolean;
customer_id: string | null;
}> {
const url = new URL(
`${this.api.baseUrl}/api/organizations/${orgId}/billing/`,
);
const response = await this.api.fetcher.fetch({
method: "get",
url,
path: "/api/organizations/",
path: `/api/organizations/${orgId}/billing/`,
});

if (!response.ok) {
throw new Error(`Failed to fetch organizations: ${response.statusText}`);
throw new Error(
`Failed to fetch organization billing: ${response.statusText}`,
);
}

const data = await response.json();
const orgs = data.results ?? data ?? [];
return orgs.map((org: { id: string; name: string; slug?: string }) => ({
id: org.id,
name: org.name,
slug: org.slug ?? org.id,
}));
return {
has_active_subscription:
typeof data.has_active_subscription === "boolean"
? data.has_active_subscription
: false,
customer_id:
typeof data.customer_id === "string" ? data.customer_id : null,
};
}

async getSignalReports(
Expand Down
7 changes: 7 additions & 0 deletions apps/twig/src/renderer/assets/images/posthog-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions apps/twig/src/renderer/assets/images/tree-bg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/twig/src/renderer/assets/images/twig-favicon-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions apps/twig/src/renderer/assets/images/twig-favicon-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 7 additions & 3 deletions apps/twig/src/renderer/assets/images/twig-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
134 changes: 0 additions & 134 deletions apps/twig/src/renderer/components/TorchGlow.tsx

This file was deleted.

Loading
Loading