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 (
+
+ );
+ })}
+
+
+