feat(web): inline chat search and global audio bar
Some checks failed
CI / test (push) Failing after 20s
Some checks failed
CI / test (push) Failing after 20s
- replace modal message search with header inline search controls - add global top audio bar linked to active inline audio player - improve chat info header variants and light theme readability
This commit is contained in:
74
web/src/store/audioPlayerStore.ts
Normal file
74
web/src/store/audioPlayerStore.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface ActiveTrack {
|
||||
src: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface AudioPlayerState {
|
||||
track: ActiveTrack | null;
|
||||
audioEl: HTMLAudioElement | null;
|
||||
isPlaying: boolean;
|
||||
volume: number;
|
||||
activate: (audioEl: HTMLAudioElement, track: ActiveTrack) => void;
|
||||
detach: (audioEl: HTMLAudioElement) => void;
|
||||
setPlaying: (audioEl: HTMLAudioElement, isPlaying: boolean) => void;
|
||||
setVolume: (audioEl: HTMLAudioElement, volume: number) => void;
|
||||
togglePlay: () => Promise<void>;
|
||||
stop: () => void;
|
||||
}
|
||||
|
||||
export const useAudioPlayerStore = create<AudioPlayerState>((set, get) => ({
|
||||
track: null,
|
||||
audioEl: null,
|
||||
isPlaying: false,
|
||||
volume: 1,
|
||||
activate: (audioEl, track) => {
|
||||
set({
|
||||
audioEl,
|
||||
track,
|
||||
isPlaying: !audioEl.paused,
|
||||
volume: audioEl.volume ?? 1,
|
||||
});
|
||||
},
|
||||
detach: (audioEl) => {
|
||||
const current = get().audioEl;
|
||||
if (current !== audioEl) {
|
||||
return;
|
||||
}
|
||||
set({ audioEl: null, track: null, isPlaying: false });
|
||||
},
|
||||
setPlaying: (audioEl, isPlaying) => {
|
||||
if (get().audioEl !== audioEl) {
|
||||
return;
|
||||
}
|
||||
set({ isPlaying });
|
||||
},
|
||||
setVolume: (audioEl, volume) => {
|
||||
if (get().audioEl !== audioEl) {
|
||||
return;
|
||||
}
|
||||
set({ volume });
|
||||
},
|
||||
togglePlay: async () => {
|
||||
const audio = get().audioEl;
|
||||
if (!audio) {
|
||||
return;
|
||||
}
|
||||
if (audio.paused) {
|
||||
await audio.play();
|
||||
set({ isPlaying: true });
|
||||
return;
|
||||
}
|
||||
audio.pause();
|
||||
set({ isPlaying: false });
|
||||
},
|
||||
stop: () => {
|
||||
const audio = get().audioEl;
|
||||
if (audio) {
|
||||
audio.pause();
|
||||
}
|
||||
set({ audioEl: null, track: null, isPlaying: false });
|
||||
},
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user