mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-22 09:34:53 +02:00
[eric] onboarding: v3 connect-first flow, live theme pad, personalized reveal
This commit is contained in:
@@ -1369,7 +1369,7 @@ const dashboardLayoutSlice = createSlice({
|
||||
|
||||
addNote(
|
||||
state,
|
||||
action: PayloadAction<{ x?: number; y?: number; expandedSessionIds?: string[]; color?: NoteColor }>,
|
||||
action: PayloadAction<{ x?: number; y?: number; expandedSessionIds?: string[]; color?: NoteColor; content?: string }>,
|
||||
) {
|
||||
const id = `note-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
||||
let posX: number, posY: number;
|
||||
@@ -1388,7 +1388,7 @@ const dashboardLayoutSlice = createSlice({
|
||||
y: posY,
|
||||
width: DEFAULT_NOTE_W,
|
||||
height: DEFAULT_NOTE_H,
|
||||
content: '',
|
||||
content: action.payload.content ?? '',
|
||||
color: action.payload.color || 'yellow',
|
||||
zOrder: state.nextZOrder++,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import type { PersonalizedStarter } from '@/shared/state/settingsSlice';
|
||||
|
||||
// Transient bridge between the v3 flow overlay and the dashboard: the overlay finishes, stashes the prep payload here, and the dashboard's reveal hook consumes it exactly once to seed the canvas.
|
||||
|
||||
export interface OnboardingV3State {
|
||||
/** True while the full-screen flow owns the window; suppresses onboarding v2. */
|
||||
flowActive: boolean;
|
||||
/** One-shot: set on finish, cleared by the reveal seeder after cards land. */
|
||||
revealPending: boolean;
|
||||
greeting: string | null;
|
||||
starters: PersonalizedStarter[];
|
||||
scanSummary: string | null;
|
||||
}
|
||||
|
||||
const initialState: OnboardingV3State = {
|
||||
flowActive: false,
|
||||
revealPending: false,
|
||||
greeting: null,
|
||||
starters: [],
|
||||
scanSummary: null,
|
||||
};
|
||||
|
||||
const onboardingV3Slice = createSlice({
|
||||
name: 'onboardingV3',
|
||||
initialState,
|
||||
reducers: {
|
||||
setFlowActive(state, action: PayloadAction<boolean>) {
|
||||
state.flowActive = action.payload;
|
||||
},
|
||||
stageReveal(state, action: PayloadAction<{ greeting: string | null; starters: PersonalizedStarter[]; scanSummary: string | null }>) {
|
||||
state.revealPending = true;
|
||||
state.greeting = action.payload.greeting;
|
||||
state.starters = action.payload.starters;
|
||||
state.scanSummary = action.payload.scanSummary;
|
||||
},
|
||||
clearReveal(state) {
|
||||
state.revealPending = false;
|
||||
state.scanSummary = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setFlowActive, stageReveal, clearReveal } = onboardingV3Slice.actions;
|
||||
export default onboardingV3Slice.reducer;
|
||||
@@ -75,6 +75,17 @@ export interface AppSettings {
|
||||
signin_method?: 'google' | 'email' | 'stripe' | null;
|
||||
/** Anonymous device id (first-run generated); stitches anon to authed PostHog Persons. */
|
||||
installation_id?: string | null;
|
||||
/** Onboarding v3 lifecycle: absent = never seen, 'done'/'skipped' once resolved. */
|
||||
onboarding_v3?: string | null;
|
||||
/** User-picked accent hex from the onboarding theme pad; null = stock accent. */
|
||||
accent_color?: string | null;
|
||||
personalized_greeting?: string | null;
|
||||
personalized_starters?: PersonalizedStarter[];
|
||||
}
|
||||
|
||||
export interface PersonalizedStarter {
|
||||
title: string;
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
export interface ActivateSubscriptionPayload {
|
||||
|
||||
@@ -18,6 +18,7 @@ import subscriptionsReducer from './subscriptionsSlice';
|
||||
import workflowsReducer from './workflowsSlice';
|
||||
import missedRunsReducer from './missedRunsSlice';
|
||||
import onboardingProgressReducer from '@/shared/state/onboardingProgressSlice';
|
||||
import onboardingV3Reducer from '@/shared/state/onboardingV3Slice';
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -40,6 +41,7 @@ export const store = configureStore({
|
||||
workflows: workflowsReducer,
|
||||
missedRuns: missedRunsReducer,
|
||||
onboardingProgress: onboardingProgressReducer,
|
||||
onboardingV3: onboardingV3Reducer,
|
||||
},
|
||||
// Disable Redux Toolkit's dev-mode invariant middleware (serializable + immutable checks). These deep-walk the entire state on every dispatch, and our state is large enough to trigger 30-50ms pauses on hot paths (agent streaming, websocket heartbeats, settings sync). Console warns "SerializableStateInvariantMiddleware took 41ms" repeatedly under load. Production builds skip these middlewares anyway, so disabling them in dev makes dev behavior match prod, no surprises at packaging time. Trade-off: serializability bugs (e.g. accidentally putting a Map or Date directly into state) won't be caught at dev time. We've shipped many versions with stable slice shapes; that risk is now low.
|
||||
middleware: (getDefault) =>
|
||||
|
||||
Reference in New Issue
Block a user