summaryrefslogtreecommitdiff
path: root/src/store/audioStore.ts
blob: 36d593d00def3636cd7ab5da421d7d5fb1b7c18a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { invoke } from '@tauri-apps/api/core';
import { create } from 'zustand';

export type AmbientSound = 'none' | 'rain' | 'cafe' | 'white_noise';

interface AudioStatus {
  available: boolean;
  playing: boolean;
  sound: AmbientSound | null;
  volume: number;
}

interface AudioStore {
  available: boolean;
  playing: boolean;
  sound: AmbientSound;
  volume: number;
  fetchStatus: () => Promise<void>;
  setSound: (sound: AmbientSound) => Promise<void>;
  setVolume: (volume: number) => Promise<void>;
}

function normalizeSound(sound: AudioStatus['sound'], playing: boolean): AmbientSound {
  if (!playing || sound === null) {
    return 'none';
  }

  return sound;
}

export const useAudioStore = create<AudioStore>((set, get) => ({
  available: true,
  playing: false,
  sound: 'none',
  volume: 0.5,

  fetchStatus: async () => {
    try {
      const status = await invoke<AudioStatus>('get_audio_status');
      set({
        available: status.available,
        playing: status.playing,
        sound: normalizeSound(status.sound, status.playing),
        volume: status.volume,
      });
    } catch (error) {
      console.error('get_audio_status error:', error);
      set({ available: false, playing: false, sound: 'none' });
    }
  },

  setSound: async (sound) => {
    try {
      if (sound === 'none') {
        await invoke('stop_ambient');
        await get().fetchStatus();
        return;
      }

      await invoke('play_ambient', { sound });
      await get().fetchStatus();
    } catch (error) {
      console.error('play_ambient error:', error);
      await get().fetchStatus();
    }
  },

  setVolume: async (volume) => {
    const nextVolume = Math.min(1, Math.max(0, volume));
    set({ volume: nextVolume });

    try {
      await invoke('set_ambient_volume', { volume: nextVolume });
      await get().fetchStatus();
    } catch (error) {
      console.error('set_ambient_volume error:', error);
      await get().fetchStatus();
    }
  },
}));