Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/mobile/src/app/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const SOUND_OPTIONS: ReadonlyArray<{ value: CompletionSound; label: string }> =
{ value: "slide", label: "Slide" },
{ value: "drop", label: "Drop" },
{ value: "icq", label: "ICQ" },
{ value: "random", label: "Random" },
];

const VOLUME_OPTIONS = [
Expand Down
5 changes: 3 additions & 2 deletions apps/mobile/src/features/chat/utils/thinkingMessages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Random thinking messages displayed while AI is generating
// Based on posthog/frontend/src/scenes/max/utils/thinkingMessages.ts

import { pickRandom } from "@/lib/pickRandom";

export const THINKING_MESSAGES = [
"Booping",
"Crunching",
Expand Down Expand Up @@ -89,8 +91,7 @@ export const THINKING_MESSAGES = [
];

export function getRandomThinkingActivity(): string {
const randomIndex = Math.floor(Math.random() * THINKING_MESSAGES.length);
return THINKING_MESSAGES[randomIndex];
return pickRandom(THINKING_MESSAGES);
}

export function getRandomThinkingMessage(): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export type CompletionSound =
| "shoot"
| "slide"
| "drop"
| "icq";
| "icq"
| "random";

export type InitialTaskMode = "plan" | "last_used";

Expand Down
25 changes: 18 additions & 7 deletions apps/mobile/src/features/tasks/utils/sounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
type CompletionSound,
usePreferencesStore,
} from "@/features/preferences/stores/preferencesStore";
import { pickRandom } from "@/lib/pickRandom";

// eslint-disable-next-line @typescript-eslint/no-require-imports
const dropAsset = require("../../../../assets/sounds/drop.mp3");
Expand All @@ -21,7 +22,9 @@ const shootAsset = require("../../../../assets/sounds/shoot.mp3");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const slideAsset = require("../../../../assets/sounds/slide.mp3");

const SOUND_ASSETS: Record<CompletionSound, number> = {
type BuiltInSound = Exclude<CompletionSound, "random">;

const SOUND_ASSETS: Record<BuiltInSound, number> = {
meep: meepAsset,
"meep-smol": meepSmolAsset,
knock: knockAsset,
Expand All @@ -32,6 +35,11 @@ const SOUND_ASSETS: Record<CompletionSound, number> = {
icq: icqAsset,
};

function resolveSoundAsset(sound: CompletionSound): number {
if (sound === "random") return pickRandom(Object.values(SOUND_ASSETS));
return SOUND_ASSETS[sound];
}

let audioModeConfigured = false;

async function ensureAudioMode(): Promise<void> {
Expand All @@ -49,12 +57,15 @@ export async function playCompletionSound(
const which = sound ?? prefs.completionSound;
const vol = (volume ?? prefs.completionVolume) / 100;
await ensureAudioMode();
const { sound: player } = await Audio.Sound.createAsync(SOUND_ASSETS[which], {
shouldPlay: true,
volume: Math.max(0, Math.min(1, vol)),
rate: playbackRate,
shouldCorrectPitch: false,
});
const { sound: player } = await Audio.Sound.createAsync(
resolveSoundAsset(which),
{
shouldPlay: true,
volume: Math.max(0, Math.min(1, vol)),
rate: playbackRate,
shouldCorrectPitch: false,
},
);
player.setOnPlaybackStatusUpdate((status) => {
if (status.isLoaded && status.didJustFinish) {
player.unloadAsync();
Expand Down
22 changes: 22 additions & 0 deletions apps/mobile/src/lib/pickRandom.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { pickRandom } from "./pickRandom";

describe("pickRandom", () => {
afterEach(() => {
vi.restoreAllMocks();
});

it("always returns an element from the pool", () => {
const pool = ["a", "b", "c", "d"];
for (let i = 0; i < 50; i++) {
expect(pool).toContain(pickRandom(pool));
}
});

it("draws a fresh pick from the random value on each call", () => {
const pool = ["a", "b", "c", "d"];
vi.spyOn(Math, "random").mockReturnValueOnce(0).mockReturnValueOnce(0.99);
expect(pickRandom(pool)).toBe("a");
expect(pickRandom(pool)).toBe("d");
});
Comment thread
Gilbert09 marked this conversation as resolved.
Outdated
});
3 changes: 3 additions & 0 deletions apps/mobile/src/lib/pickRandom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function pickRandom<T>(pool: readonly T[]): T {
return pool[Math.floor(Math.random() * pool.length)];
}
Comment thread
Gilbert09 marked this conversation as resolved.
Loading