From 089774dc3ef9fd99dd4a3e0de4d44a3c1b10e377 Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:13:32 +0200 Subject: [PATCH] chore(orbit): configurable shuffle interval Co-Authored-By: Claude Opus 4.7 (1M context) --- src/api/orbit.ts | 13 ++++++- src/components/OrbitSessionBar.tsx | 4 +-- src/components/OrbitSettingsPopover.tsx | 33 +++++++++++++++++- src/hooks/useOrbitHost.ts | 4 +-- src/locales/de.ts | 8 +++-- src/locales/en.ts | 8 +++-- src/styles/components.css | 46 +++++++++++++++++++++++++ src/utils/orbit.ts | 24 ++++++++++--- 8 files changed, 126 insertions(+), 14 deletions(-) diff --git a/src/api/orbit.ts b/src/api/orbit.ts index 994900d2..ca66d339 100644 --- a/src/api/orbit.ts +++ b/src/api/orbit.ts @@ -106,16 +106,27 @@ export interface OrbitState { * Host-configurable rules. All default to `true`, i.e. the feature runs * "all on" for new sessions. Toggled via the Orbit-bar settings popover. */ +/** Minute presets offered to the host in the Orbit settings popover. */ +export const ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN = [1, 5, 10, 15, 30] as const; +export type OrbitShuffleIntervalMin = typeof ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN[number]; + export interface OrbitSettings { /** Guest suggestions go straight into the host's play queue. */ autoApprove: boolean; - /** Queue is reshuffled every `ORBIT_SHUFFLE_INTERVAL_MS`. */ + /** Whether the auto-shuffle cycle runs at all. */ autoShuffle: boolean; + /** + * Minutes between each auto-shuffle cycle. Must be one of + * `ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN`. Older sessions that predate this + * field fall back to 15 via `effectiveShuffleIntervalMs`. + */ + shuffleIntervalMin?: OrbitShuffleIntervalMin; } export const ORBIT_DEFAULT_SETTINGS: OrbitSettings = { autoApprove: true, autoShuffle: true, + shuffleIntervalMin: 15, }; /** What the guest's outbox-playlist comment holds (heartbeat only, for now). */ diff --git a/src/components/OrbitSessionBar.tsx b/src/components/OrbitSessionBar.tsx index c6fd671f..d33ed06f 100644 --- a/src/components/OrbitSessionBar.tsx +++ b/src/components/OrbitSessionBar.tsx @@ -8,8 +8,8 @@ import { endOrbitSession, leaveOrbitSession, computeOrbitDriftMs, + effectiveShuffleIntervalMs, } from '../utils/orbit'; -import { ORBIT_SHUFFLE_INTERVAL_MS } from '../utils/orbit'; import { estimateLivePosition } from '../api/orbit'; import OrbitParticipantsPopover from './OrbitParticipantsPopover'; import OrbitExitModal from './OrbitExitModal'; @@ -69,7 +69,7 @@ export default function OrbitSessionBar() { ); - const untilShuffle = Math.max(0, (state.lastShuffle + ORBIT_SHUFFLE_INTERVAL_MS) - nowMs); + const untilShuffle = Math.max(0, (state.lastShuffle + effectiveShuffleIntervalMs(state)) - nowMs); // Guest-only: detect drift from the host's estimated live position. const guestPlayback = usePlayerStore.getState(); diff --git a/src/components/OrbitSettingsPopover.tsx b/src/components/OrbitSettingsPopover.tsx index 60eaa156..2070052f 100644 --- a/src/components/OrbitSettingsPopover.tsx +++ b/src/components/OrbitSettingsPopover.tsx @@ -4,7 +4,7 @@ import { Shuffle } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useOrbitStore } from '../store/orbitStore'; import { updateOrbitSettings, triggerOrbitShuffleNow } from '../utils/orbit'; -import { ORBIT_DEFAULT_SETTINGS } from '../api/orbit'; +import { ORBIT_DEFAULT_SETTINGS, ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN, type OrbitShuffleIntervalMin } from '../api/orbit'; import { showToast } from '../utils/toast'; interface Props { @@ -82,6 +82,37 @@ export default function OrbitSettingsPopover({ anchorRef, onClose }: Props) { +
+
+
{t('orbit.settingShuffleInterval')}
+
{t('orbit.settingShuffleIntervalHint')}
+
+
+ {ORBIT_SHUFFLE_INTERVAL_PRESETS_MIN.map(min => { + const active = (settings.shuffleIntervalMin ?? 15) === min; + return ( + + ); + })} +
+
+