Spaces:
Running
Running
Commit History
-
style(emotions): truncate long tile labels with an ellipsis instead of wrapping
Co-authored-by: Cursor <cursoragent@cursor.com>cde39d2 -
style(emotions): render the blog link as an underlined primary link
Co-authored-by: Cursor <cursoragent@cursor.com>6b4862e
-
feat(emotions): link to the blog post from the wheel view
Adds a low-key footer link to the article documenting how the emotion library was recorded, pinned to the bottom edge and hidden while a family panel is open so it never competes with the emoji grid. Co-authored-by: Cursor <cursoragent@cursor.com>67d4392
-
fix(audio): fetch companion sounds as .ogg after dataset migration from WAV
Co-authored-by: Cursor <cursoragent@cursor.com>2afdd7b
-
feat(emotions): show every play in the wheel center, drop top strip
Tile-triggered plays now swap the wheel's center pill into the now-playing tile (emoji + progress + STOP) just like random plays, so the active emotion always reads at the center of the wheel. Remove the separate top NowPlayingStrip (and its now-dead playSource state). Co-authored-by: Cursor <cursoragent@cursor.com>d9b8e38
-
feat(emotions): make wheel/aim ticks more audible
Bump the tick volume so the per-family cues snap during the aim sweep and the tap roulette. Co-authored-by: Cursor <cursoragent@cursor.com>068abf3
-
feat(emotions): center-only emoji roll for aimed swipe
An aimed center release now flashes through a few family emojis with ticks at the center pill - the wheel stays still - then settles on the aimed family and plays, instead of snapping to it instantly. The wheel highlight roulette stays reserved for the classic tap random. Each family crossing during the live drag also rolls the dice and fires a haptic notch for a notched, roulette-like sweep. Co-authored-by: Cursor <cursoragent@cursor.com>dbf144b -
feat(emotions): progressive onboarding for random + aim gesture
Replace the single dismiss-on-interaction hint with a progressive two-step flow and drop the always-pulsing center halo: - intro copy (tap a wedge / tap center) shown until the first random; - a focused "hold and aim" tip that persists until the user actually performs an aimed drag (never auto-dismisses); - onboarding flags are bypassed in dev so hints replay every reload. Co-authored-by: Cursor <cursoragent@cursor.com>a81f688
-
feat(emotions): return to safe-rest pose on stop and completion
Drive the robot back to the canonical INIT_POSE whenever an emotion is stopped manually or finishes naturally, instead of freezing on the last (often tilted/splayed) frame. - TrajectoryPlayer.returnToBase() delegates to the SDK's safelyReturnToPose (INIT_POSE + daemon-mirrored scaledDuration), avoiding the re-implemented pose/duration math anti-pattern (§14.6). Wired into the manual-stop and natural-completion paths in EmotionsView. - Pin reachy-mini-sdk to 1.8.0-main.8c428a1 for the /animation subpath (safelyReturnToPose/INIT_POSE/scaledDuration not yet in 1.8.0 stable). - Pre-decimate trajectories to 50 Hz before upload (emotionsLibrary.downsampleByHz) and match PLAY_FREQUENCY to the wireless control loop, halving the WebRTC upload with no motion fidelity loss (daemon re-interpolates between frames). Co-authored-by: Cursor <cursoragent@cursor.com>ade06b6
-
fix(emotions): make NowPlayingStrip loading state build on MUI v9
Verified signatureThe previously deployed loading-strip used Stack's `alignItems` as a top-level prop, which MUI v9 removed (it lives in `sx` now), breaking the Space's tsc build. Move alignItems into sx on the two row Stacks, keeping the delay-gated "Loading..." label + indeterminate sweep intact.a3fe6cc -
feat(emotions): show light loading label in the top strip during prepare
Verified signatureMount the NowPlayingStrip during the loading window (delay-gated 200ms so cache-warm plays never flash it) and render a discreet "Loading..." label where the emotion title will land, with an indeterminate sweep on the top line. Content swaps in place to the resolved title once playback streams.904e5c9 -
feat(emotions): explicit loading transition state for daemon-side playback
Verified signatureThe daemon-side playMove pipeline introduces a loading window (trajectory upload + initial-goto prelude) between tap and motion, which previously read as a frozen empty progress bar. Surface an explicit "preparing" state instead: indeterminate sweep on the tapped tile's bar and on the center pill's progress arc, a soft breathe on the center emoji, and a "Preparing..." label in place of the (inert) Stop cue while loading.7bb4b01
-
chore(deps): upgrade MUI to v9.0.1
- @mui/material: ^7.3.5 -> ^9.0.1 - @mui/icons-material: ^7.3.5 -> ^9.0.1 - Ran `npx @mui/codemod@latest v9.0.0/system-props src/` (codemod output: 2 files transformed, src/components/EmotionsView.tsx and src/components/emotions/NowPlayingStrip.tsx). Note: the umbrella `v9.0.0` transform does not exist in @mui/codemod@9.0.1 - only the `v9.0.0/system-props` sub-rule is shipped. - Lockfile regenerated from scratch (no --legacy-peer-deps needed; the SDK's transitive @mui/material@7.3.11 dedupe is harmless). - Manual fix in src/theme.ts: MUI v9 removed the variant-color combination slots (`outlinedPrimary`, `containedPrimary`, etc.) from `MuiButton`'s `styleOverrides`. Migrated `outlinedPrimary` to the new `variants` API (`{ props: { variant: 'outlined', color: 'primary' }, style: ... }`). Build verified locally with `npm run build`. Push goes to the `chore/upgrade-mui-9` branch so the user can validate the deployed Space before merging to `main`. Co-authore…a9721bc
-
refactor(player): drive playback through daemon-side playMove
Switch the trajectory player from a client-side rAF stream of setTarget calls to robot.playMove. The daemon now consumes the trajectory on its hard real-time control loop (≥100 Hz), so jank in the browser tab, GC pauses, fluctuating WebRTC links, and sluggish phone CPUs can no longer drop motion frames or desync the companion audio. Key wins: * Smooth prelude before every emotion: initialGotoDuration is computed from the present robotState vs the first frame using the distance-scaled formula from RemiFabre/reachy-mini-js- practices (head magic-mm + antenna deg + body deg, slowest channel wins, clamped to [0.2 s, 1.5 s]). The daemon routes the prelude through the same gotoTarget that got the atomic-target-pin fix in pollen-robotics/reachy_mini#1138, so the "torque off -> move by hand -> play emotion" path can no longer produce a brutal snap. * Companion audio in sample-accurate lock-step: audio blobs are fetched alongside trajectories, cached in memory, and shipped …c37ea96 -
perf(emotions): kill first-open family panel flicker
The first time a user opened a family wedge, useFamilyDurations fired one fetch + setState per emotion in that family (up to 13 for Joy), each landing during the panel's 450ms mount animation and triggering a re-render with a fresh duration-badge fade-in. Combined with the wheel's min-height transition and the smooth scrollTo, the panel visibly flickered on first open and was clean on subsequent opens - because the in-memory trajectory cache was warm by then. Three changes that together flatten the first-open path to "single render with all badges in place": 1. emotionsLibrary: sidecar synchronous duration cache (durationsByIdSync) populated alongside trajectoryCache after a successful parse, plus a getCachedDurationSec(id) sync getter so render code can seed state from already-resolved trajectories. 2. EmotionsView: background preloader kicked off at view mount, walking every emotion through loadTrajectory with concurrency 4 and requestIdleCallback scheduling (setTim…b367818 -
chore(deps): drop vendored host, use @pollen-robotics/reachy-mini-sdk/host
The host shell now ships from the same npm package as the SDK under the ./host subpath. Removes the vendor/reachy-mini-host copy and pins the SDK to the npm `latest` dist-tag. Co-authored-by: Cursor <cursoragent@cursor.com>27f8642
-
chore(embed): restore ?embedded=1 query flag for legacy compatibility
- Revert dispatcher flag from ?embed=1 back to ?embedded=1 - Accept both ?embedded=1 and ?embed=1 in dispatch (transient compat) - Re-vendor reachy-mini-host dist (rebuilt against the legacy flag) - Bundle incidental UI/data tweaks (Plutchik wheel, theme, etc.) Co-authored-by: Cursor <cursoragent@cursor.com>112ac2f
-
fix(emotions): +1/3 more on family panel open (615ms wheel / 450ms panel)
Co-authored-by: Cursor <cursoragent@cursor.com>6f3aeb8 -
fix(emotions): slow down family panel open by ~1.4x
The 320 ms wheel-collapse + 240 ms panel fade-in felt rushed on desktop where the eye has more travel distance to follow. Bump both transitions in lockstep and switch the panel fade easing to the same cubic-bezier as the wheel so the two motions read as a single coordinated event: - wheel min-height + padding-bottom : 320 ms -> 460 ms - panel mount fade + 6 px slide : 240 ms -> 340 ms (now cubic-bezier(0.32, 0.72, 0, 1) instead of `ease`) Co-authored-by: Cursor <cursoragent@cursor.com>5839e2b -
fix(emotions): cap family panel width to 480px on desktop
The 3-column emotion grid used to stretch full-viewport on wide screens, producing oversized tiles that broke the visual rhythm with the 380px-capped wheel above. The panel now sits in a 480px-max centered column (480 = wheel + breathing room for the 3-tile row), keeping mobile untouched while restoring a tight, balanced desktop layout. Co-authored-by: Cursor <cursoragent@cursor.com>74c9b0e -
chore: bump host to 0.3.6 (welcome anim fixes + mobile-parity picker)
Refresh vendored @reachy-mini/host: - welcome-back animation triggers only on user-initiated sign-in (no more spurious play on first load / page reload) - one-shot latch prevents the overlay from re-firing in a loop when isPostOauthReturn stays sticky - picker robot card mirrors the mobile app exactly: ListItemButton, antenna-peeking RobotAvatar, Wi-Fi/USB TransportChip, lock 20px + text.disabled, "In use · {app}" tooltip placement left Also fix `devToken: { username }` -> `userName` to match the host's MountHostOptions contract. Co-authored-by: Cursor <cursoragent@cursor.com>6469764
-
feat: migrate to @reachy-mini/host iframe architecture
ThibaudThe app now boots through the shared host shell (sign-in, robot picker, WebRTC handshake) and runs inside an iframe with a postMessage bridge for live theme + config updates. What changed: - index.html: trimmed to a dispatcher that decides standalone vs embed based on `?embed=1`. Inline boot script sets the theme before the JS bundle loads to avoid a palette flash. - src/dispatch.ts (new): branches between `./embed` (the app) and `@reachy-mini/host/auto` (the host shell). Carries an inline TODO for the eventual CDN-import swap. - src/embed.tsx (new): replaces the old `main.tsx` + `App.tsx`. Calls `connectToHost()` to receive a live SDK instance, then mounts `<EmotionsView>` inside MUI's ThemeProvider. Reacts to `onThemeChange` and `onLeave` from the host. - src/sdk-types.ts: re-exports the canonical SDK types from `@reachy-mini/host` instead of duplicating them. - Deleted: every component that used to render the pre-session UI (SignInView, RobotPickerView, Conne…1d21c88
-
fix(picker): match the mobile shell's RobotAvatar exactly
Swap the 14 px rounded square + reachy-buste plate for the mobile shell's circular reachy-standard disc (subtle neutral tint, antennas overflowing the rim, head body centred via translate -50%/-60%). The card surface stays unchanged - only the avatar changes - so users transitioning between the mobile app and this app see the exact same iconography for the same robot, which is what the picker promises in the first place. Also ships `reachy-standard.svg` in `public/` so nginx serves it directly from the bundle. Co-authored-by: Cursor <cursoragent@cursor.com>6bf57a1 -
feat(picker): adopt reachy-buste hero + avatar in the robot picker
Mirror the host shell's `RobotPickerView` so the standalone emotions experience feels identical to the one users get when they enter through the host: a 144 px reachy-buste illustration above the "Your Reachies" title (and the empty-state copy), and a buste-cropped avatar plate on each row instead of the floating reachy-head silhouette. The asset is the same one the mobile shell ships in its ScanScreen, so users transitioning between the mobile app, the host, and this app see the same identity throughout. Co-authored-by: Cursor <cursoragent@cursor.com>57065b6 -
fix(wheel): switch dice strip to inline conditional styles for reliable show/hide
Co-authored-by: Cursor <cursoragent@cursor.com>9ccbea2 -
fix(wheel): curve family labels along the outer arc to avoid emoji overlap
Co-authored-by: Cursor <cursoragent@cursor.com>8e4d1e2 -
chore: add ?demo=wheel route to preview the wheel without a robot
Co-authored-by: Cursor <cursoragent@cursor.com>1cd38c1 -
feat: rewrite the Plutchik wheel to match the desktop design
The first pass painted the wheel as 8 coloured petals with a white inner disc and dot-density indicators, which read as cluttered and broke the visual identity established by the desktop dashboard's EmotionWheel. This commit reverts the wheel to that proven design language: - transparent slices separated by 1 px lines (no coloured fills); - accent stroke on hover / pressed / active slice instead of fills; - soft radial-gradient background with a 1 px outer ring; - two real CSS-dotted dice (port of the desktop DiceIcon) with the shake animation during spin; - the centre pill button shows the dice on hover / spin and the word "RANDOM" the rest of the time, slid via CSS transitions; - spin animation walks the slices CW with a power-eased delay, re-randomising the dice values each step; - bite tick fires per step, dice roll fires once on spin start. Sound assets ported verbatim from the desktop app (`src/assets/sounds/dice.mp3` + `bite.mp3`). Co-authored-by: Cursor <cursoragent@cu…2b1500b -
fix: brand the TopBar with the Emotions name + new icon
Co-authored-by: Cursor <cursoragent@cursor.com>55d2403 -
feat: bootstrap Reachy Mini Emotions Space
A mobile-only webapp that browses the Reachy Mini emotion library through a Plutchik-inspired wheel. - Eight coloured sectors (Joy / Trust / Fear / Surprise / Sadness / Disgust / Anger / Anticipation) drive a hand-curated mapping of the 79 emotions in pollen-robotics/reachy-mini-emotions-library. - Tap a sector → SwipeableDrawer drill-down with emoji + label + duration + description for every emotion in that family. - Centre dice spins to a random emotion with a GSAP-style flourish. - Trajectories stream straight from the HF dataset CDN: the player fetches the JSON, parses head (4x4 nested or flat 16) + antennas + body_yaw frames, then sends set_full_target via robot.setTarget at vsync cadence with client-side LERP between source samples. - Companion .wav (when present) plays via Web Audio in lock-step. - Sticky now-playing strip reflects status / progress / cancel, iOS safe-area aware. - Boots through the same useReachyMini lifecycle as telepresence: HF OAuth (or .env…87a0733