Skip to content
Open
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
8 changes: 7 additions & 1 deletion apps/code/src/renderer/components/GlobalEventHandlers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useSidebarStore } from "@features/sidebar/stores/sidebarStore";
import { useTasks } from "@features/tasks/hooks/useTasks";
import { useFocusWorkspace } from "@features/workspace/hooks/useFocusWorkspace";
import { useWorkspaces } from "@features/workspace/hooks/useWorkspace";
import { useFeatureFlag } from "@hooks/useFeatureFlag";
import { SHORTCUTS } from "@renderer/constants/keyboard-shortcuts";
import { useTRPC } from "@renderer/trpc";
import type { Task } from "@shared/types";
Expand Down Expand Up @@ -170,10 +171,15 @@ export function GlobalEventHandlers({
setReviewMode(currentTaskId, mode === "closed" ? "split" : "closed");
}, [currentTaskId, getReviewMode, setReviewMode]);

const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");

useHotkeys(SHORTCUTS.TOGGLE_LEFT_SIDEBAR, toggleLeftSidebar, globalOptions);
useHotkeys(SHORTCUTS.TOGGLE_REVIEW_PANEL, handleToggleReview, globalOptions);
useHotkeys(SHORTCUTS.SHORTCUTS_SHEET, onToggleShortcutsSheet, globalOptions);
useHotkeys(SHORTCUTS.INBOX, navigateToInbox, globalOptions);
useHotkeys(SHORTCUTS.INBOX, navigateToInbox, {
...globalOptions,
enabled: !inboxHidden,
});
useHotkeys(SHORTCUTS.PREV_TASK, handlePrevTask, globalOptions, [
handlePrevTask,
]);
Expand Down
10 changes: 9 additions & 1 deletion apps/code/src/renderer/components/KeyboardShortcutsSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFeatureFlag } from "@hooks/useFeatureFlag";
import { Box, Dialog, Flex, Text } from "@radix-ui/themes";
import {
CATEGORY_LABELS,
Expand Down Expand Up @@ -130,7 +131,14 @@ function ShortcutsHeader() {
}

export function KeyboardShortcutsList() {
const shortcutsByCategory = useMemo(() => getShortcutsByCategory(), []);
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");
const shortcutsByCategory = useMemo(() => {
const grouped = getShortcutsByCategory();
if (inboxHidden) {
grouped.navigation = grouped.navigation.filter((s) => s.id !== "inbox");
}
return grouped;
}, [inboxHidden]);

const categoryOrder: ShortcutCategory[] = [
"general",
Expand Down
3 changes: 2 additions & 1 deletion apps/code/src/renderer/components/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function MainLayout() {
} = useShortcutsSheetStore();
const { data: tasks } = useTasks();
const { showPrompt, isChecking, check, dismiss } = useConnectivity();
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");
const billingEnabled = useFeatureFlag(BILLING_FLAG);

// Space switcher data
Expand Down Expand Up @@ -108,7 +109,7 @@ export function MainLayout() {

{view.type === "folder-settings" && <FolderSettingsView />}

{view.type === "inbox" && <InboxView />}
{view.type === "inbox" && !inboxHidden && <InboxView />}

{view.type === "archived" && <ArchivedTasksView />}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function OnboardingFlow() {
const {
currentStep,
activeSteps,
isLastStep,
direction,
next,
back,
Expand All @@ -46,12 +47,10 @@ export function OnboardingFlow() {
);
usePrefetchSignalData();

useHotkeys("right", next, { enableOnFormTags: false }, [next]);
useHotkeys("left", back, { enableOnFormTags: false }, [back]);
const handleNext = isLastStep ? completeOnboarding : next;

const handleComplete = () => {
completeOnboarding();
};
useHotkeys("right", handleNext, { enableOnFormTags: false }, [handleNext]);
useHotkeys("left", back, { enableOnFormTags: false }, [back]);

const footerRight = (
<Flex gap="5">
Expand All @@ -75,7 +74,7 @@ export function OnboardingFlow() {
size="1"
variant="ghost"
color="gray"
onClick={handleComplete}
onClick={completeOnboarding}
style={{ opacity: 0.5 }}
>
<ArrowRight size={14} weight="bold" />
Expand All @@ -100,7 +99,7 @@ export function OnboardingFlow() {
transition={{ duration: 0.3 }}
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<WelcomeScreen onNext={next} />
<WelcomeScreen onNext={handleNext} />
</motion.div>
)}

Expand All @@ -115,7 +114,7 @@ export function OnboardingFlow() {
transition={{ duration: 0.3 }}
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<ProjectSelectStep onNext={next} onBack={back} />
<ProjectSelectStep onNext={handleNext} onBack={back} />
</motion.div>
)}

Expand All @@ -130,7 +129,7 @@ export function OnboardingFlow() {
transition={{ duration: 0.3 }}
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<InviteCodeStep onNext={next} onBack={back} />
<InviteCodeStep onNext={handleNext} onBack={back} />
</motion.div>
)}

Expand All @@ -146,7 +145,7 @@ export function OnboardingFlow() {
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<GitIntegrationStep
onNext={next}
onNext={handleNext}
onBack={back}
selectedDirectory={selectedDirectory}
detectedRepo={detectedRepo}
Expand All @@ -167,7 +166,7 @@ export function OnboardingFlow() {
transition={{ duration: 0.3 }}
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<CliInstallStep onNext={next} onBack={back} />
<CliInstallStep onNext={handleNext} onBack={back} />
</motion.div>
)}

Expand All @@ -182,7 +181,7 @@ export function OnboardingFlow() {
transition={{ duration: 0.3 }}
style={{ width: "100%", flex: 1, minHeight: 0 }}
>
<SignalsStep onNext={handleComplete} onBack={back} />
<SignalsStep onNext={handleNext} onBack={back} />
</motion.div>
)}
</AnimatePresence>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useFeatureFlag } from "@hooks/useFeatureFlag";
import {
ArrowRight,
ChartLine,
Expand All @@ -8,37 +9,42 @@ import {
} from "@phosphor-icons/react";
import { Button, Flex, Text } from "@radix-ui/themes";
import explorerHog from "@renderer/assets/images/hedgehogs/explorer-hog.png";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { FeatureListItem } from "./FeatureListItem";
import { OnboardingHogTip } from "./OnboardingHogTip";
import { StepActions } from "./StepActions";

const FEATURES = [
const ALL_FEATURES = [
{
id: "signals-inbox",
icon: <Tray size={24} />,
title: "Your signals inbox",
description:
"Automatically surfaces the highest-impact work from your product data so you always know what to do next.",
},
{
id: "product-data",
icon: <ChartLine size={24} />,
title: "Product data as context",
description:
"Your agents have context from your analytics, session replays and feature flags built in.",
},
{
id: "any-model",
icon: <Robot size={24} />,
title: "Any model, any harness",
description:
"Bring your own agent framework or use our built-in harnesses. Swap models without changing your workflow.",
},
{
id: "ship-work",
icon: <Cloud size={24} />,
title: "Ship work, not messages",
description:
"Run tasks in parallel across local and cloud environments. Work gets done whether you're watching or not.",
},
{
id: "review-ship",
icon: <GitPullRequest size={24} />,
title: "Review and ship with confidence",
description:
Expand All @@ -51,18 +57,26 @@ interface WelcomeScreenProps {
}

const CYCLE_INTERVAL_MS = 2500;
const CYCLE_START_DELAY_MS = FEATURES.length * 100 + 400;
const CYCLE_START_DELAY_MS = ALL_FEATURES.length * 100 + 400;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 CYCLE_START_DELAY_MS uses all-features count regardless of flag

CYCLE_START_DELAY_MS is a module-level constant computed from ALL_FEATURES.length (5), so when inbox is disabled and only 4 features render, the stagger delay before cycling begins is 100 ms longer than necessary. The constant could be moved inside the component (or derived from features) to stay in sync with the actual list length.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/onboarding/components/WelcomeScreen.tsx
Line: 60

Comment:
**`CYCLE_START_DELAY_MS` uses all-features count regardless of flag**

`CYCLE_START_DELAY_MS` is a module-level constant computed from `ALL_FEATURES.length` (5), so when inbox is disabled and only 4 features render, the stagger delay before cycling begins is 100 ms longer than necessary. The constant could be moved inside the component (or derived from `features`) to stay in sync with the actual list length.

How can I resolve this? If you propose a fix, please make it concise.


export function WelcomeScreen({ onNext }: WelcomeScreenProps) {
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");
const features = useMemo(
() =>
inboxHidden
? ALL_FEATURES.filter((f) => f.id !== "signals-inbox")
: ALL_FEATURES,
[inboxHidden],
);
const [activeIndex, setActiveIndex] = useState(-1);
const timerRef = useRef<ReturnType<typeof setInterval>>(null);

const startCycling = useCallback(() => {
if (timerRef.current) clearInterval(timerRef.current);
timerRef.current = setInterval(() => {
setActiveIndex((prev) => (prev + 1) % FEATURES.length);
setActiveIndex((prev) => (prev + 1) % features.length);
}, CYCLE_INTERVAL_MS);
}, []);
}, [features.length]);

useEffect(() => {
const timeout = setTimeout(() => {
Expand Down Expand Up @@ -126,7 +140,7 @@ export function WelcomeScreen({ onNext }: WelcomeScreenProps) {
</Flex>

<Flex direction="column" style={{ width: "100%", gap: 8 }}>
{FEATURES.map((feature, index) => (
{features.map((feature, index) => (
<FeatureListItem
key={feature.title}
icon={feature.icon}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useAuthStateValue } from "@features/auth/hooks/authQueries";
import { useOnboardingStore } from "@features/onboarding/stores/onboardingStore";
import { useFeatureFlag } from "@hooks/useFeatureFlag";
import { trpcClient } from "@renderer/trpc/client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ONBOARDING_STEPS, type OnboardingStep } from "../types";
Expand Down Expand Up @@ -78,13 +79,18 @@ export function useOnboardingFlow() {
);

const hasCodeAccess = useAuthStateValue((state) => state.hasCodeAccess);
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");

const activeSteps = useMemo(() => {
let steps = ONBOARDING_STEPS as OnboardingStep[];
if (hasCodeAccess === true) {
return ONBOARDING_STEPS.filter((s) => s !== "invite-code");
steps = steps.filter((s) => s !== "invite-code");
}
return ONBOARDING_STEPS;
}, [hasCodeAccess]);
if (inboxHidden) {
steps = steps.filter((s) => s !== "signals");
}
return steps;
}, [hasCodeAccess, inboxHidden]);

useEffect(() => {
if (!activeSteps.includes(currentStep)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,18 @@ export function SettingsDialog() {
const client = useOptionalAuthenticatedClient();
const { data: user } = useCurrentUser({ client });
const { seat, planLabel } = useSeat();
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");
const billingEnabled = useFeatureFlag(BILLING_FLAG);
const logoutMutation = useLogoutMutation();

const sidebarItems = useMemo(
() =>
billingEnabled
? SIDEBAR_ITEMS
: SIDEBAR_ITEMS.filter((item) => item.id !== "plan-usage"),
[billingEnabled],
SIDEBAR_ITEMS.filter((item) => {
if (item.id === "plan-usage" && !billingEnabled) return false;
if (item.id === "signals" && inboxHidden) return false;
return true;
}),
[billingEnabled, inboxHidden],
);

useHotkeys("escape", close, {
Expand Down
19 changes: 12 additions & 7 deletions apps/code/src/renderer/features/sidebar/components/SidebarMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "@features/tasks/hooks/useArchiveTask";
import { useTasks, useUpdateTask } from "@features/tasks/hooks/useTasks";
import { useWorkspaces } from "@features/workspace/hooks/useWorkspace";
import { useFeatureFlag } from "@hooks/useFeatureFlag";
import { useTaskContextMenu } from "@hooks/useTaskContextMenu";
import { ScrollArea, Separator } from "@posthog/quill";
import { Box, Flex } from "@radix-ui/themes";
Expand Down Expand Up @@ -55,10 +56,12 @@ function SidebarMenuComponent() {
const sidebarData = useSidebarData({
activeView: view,
});
const inboxHidden = useFeatureFlag("posthog-code-inbox-hidden");
const inboxPollingActive = useRendererWindowFocusStore((s) => s.focused);
const { data: inboxProbe } = useInboxReports(
{ status: INBOX_PIPELINE_STATUS_FILTER },
{
enabled: !inboxHidden,
refetchInterval: inboxPollingActive ? INBOX_REFETCH_INTERVAL_MS : false,
refetchIntervalInBackground: false,
staleTime: inboxPollingActive ? INBOX_REFETCH_INTERVAL_MS : 15_000,
Expand Down Expand Up @@ -277,13 +280,15 @@ function SidebarMenuComponent() {
/>
</Box>

<Box>
<InboxItem
isActive={sidebarData.isInboxActive}
onClick={handleInboxClick}
signalCount={inboxSignalCount}
/>
</Box>
{!inboxHidden && (
<Box>
<InboxItem
isActive={sidebarData.isInboxActive}
onClick={handleInboxClick}
signalCount={inboxSignalCount}
/>
</Box>
)}

<Box>
<SkillsItem
Expand Down
Loading