[eric] perf: identity-stable selectors, tool rows stop subscribing to whole slices, thumbnails wait out interactions

This commit is contained in:
ciregenz
2026-08-05 10:06:15 -07:00
parent 59b982bf37
commit efef227779
10 changed files with 109 additions and 80 deletions
@@ -17,13 +17,15 @@ function scheduleFor(cadence: string) {
return { ...base, repeat_unit: 'week' as const, on_days: [1] };
}
// Identity-stable fallback: `?? []` inline minted a fresh array per store tick and re-rendered this on every streamed character.
const EMPTY_AUTOMATIONS: PersonalizedAutomation[] = [];
const CADENCE_LABEL: Record<string, string> = { daily: 'daily at 9am', weekday: 'weekdays at 9am', weekly: 'Mondays at 9am' };
// Prep proposed routines worth automating for THIS user; each chip is one click to a real scheduled workflow. Falls back to a generic morning brief when prep gave none. One-shot per install (localStorage), so a returning user is never re-nagged.
const AutomationChips: React.FC<{ c: ClaudeTokens }> = ({ c }) => {
const dispatch = useAppDispatch();
const model = useAppSelector((s) => s.settings.data.default_model);
const proposed = useAppSelector((s) => s.settings.data.personalized_automations ?? []);
const proposed = useAppSelector((s) => s.settings.data.personalized_automations) ?? EMPTY_AUTOMATIONS;
const items: PersonalizedAutomation[] = proposed.length > 0 ? proposed.slice(0, 3) : [
{ title: 'Morning brief', prompt: "Put together my morning brief: today's date, my location's weather, and top tech + world headlines. Keep it under 300 words and save it as a dated note on my dashboard.", cadence: 'daily' },
];
@@ -8,6 +8,10 @@ import { AnimatePresence, motion } from 'framer-motion';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import { useAppDispatch, useAppSelector } from '@/shared/hooks';
import { createWorkflow } from '@/shared/state/workflowsSlice';
import type { PersonalizedStarter } from '@/shared/state/settingsSlice';
// Identity-stable fallback so an absent settings field can't re-render this per store tick.
const EMPTY_STARTERS: PersonalizedStarter[] = [];
const OFFER_DONE_KEY = 'openswarm.schedule-offer.v1';
@@ -31,7 +35,7 @@ const ScheduleOfferToast: React.FC<{ dashboardId: string }> = ({ dashboardId })
const dispatch = useAppDispatch();
const [resolved, setResolved] = useState(offerAlreadyResolved);
const [confirmText, setConfirmText] = useState<string | null>(null);
const starters = useAppSelector((s) => s.settings.data.personalized_starters ?? []);
const starters = useAppSelector((s) => s.settings.data.personalized_starters) ?? EMPTY_STARTERS;
const sessions = useAppSelector((s) => s.agents.sessions);
const model = useAppSelector((s) => s.settings.data.default_model);