Initial release: DictIA v0.8.14-alpha (fork de Speakr, AGPL-3.0)
This commit is contained in:
147
static/js/composables/usePlayer.js
Normal file
147
static/js/composables/usePlayer.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Audio Player composable
|
||||
* Handles audio playback functionality
|
||||
*/
|
||||
|
||||
import { ref, computed, watch } from 'vue';
|
||||
|
||||
export function usePlayer() {
|
||||
// State
|
||||
const isPlaying = ref(false);
|
||||
const currentTime = ref(0);
|
||||
const duration = ref(0);
|
||||
const playbackRate = ref(1.0);
|
||||
const audioElement = ref(null);
|
||||
|
||||
// Computed
|
||||
const progress = computed(() => {
|
||||
if (!duration.value) return 0;
|
||||
return (currentTime.value / duration.value) * 100;
|
||||
});
|
||||
|
||||
const formattedCurrentTime = computed(() => {
|
||||
return formatTime(currentTime.value);
|
||||
});
|
||||
|
||||
const formattedDuration = computed(() => {
|
||||
return formatTime(duration.value);
|
||||
});
|
||||
|
||||
// Methods
|
||||
const formatTime = (seconds) => {
|
||||
if (!seconds || isNaN(seconds)) return '0:00';
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
const initPlayer = (audio) => {
|
||||
audioElement.value = audio;
|
||||
|
||||
if (!audio) return;
|
||||
|
||||
audio.addEventListener('loadedmetadata', () => {
|
||||
duration.value = audio.duration;
|
||||
});
|
||||
|
||||
audio.addEventListener('timeupdate', () => {
|
||||
currentTime.value = audio.currentTime;
|
||||
});
|
||||
|
||||
audio.addEventListener('play', () => {
|
||||
isPlaying.value = true;
|
||||
});
|
||||
|
||||
audio.addEventListener('pause', () => {
|
||||
isPlaying.value = false;
|
||||
});
|
||||
|
||||
audio.addEventListener('ended', () => {
|
||||
isPlaying.value = false;
|
||||
currentTime.value = 0;
|
||||
});
|
||||
};
|
||||
|
||||
const play = () => {
|
||||
if (audioElement.value) {
|
||||
audioElement.value.play();
|
||||
}
|
||||
};
|
||||
|
||||
const pause = () => {
|
||||
if (audioElement.value) {
|
||||
audioElement.value.pause();
|
||||
}
|
||||
};
|
||||
|
||||
const togglePlayPause = () => {
|
||||
if (isPlaying.value) {
|
||||
pause();
|
||||
} else {
|
||||
play();
|
||||
}
|
||||
};
|
||||
|
||||
const seek = (time) => {
|
||||
if (audioElement.value) {
|
||||
audioElement.value.currentTime = time;
|
||||
currentTime.value = time;
|
||||
}
|
||||
};
|
||||
|
||||
const seekPercent = (percent) => {
|
||||
if (audioElement.value && duration.value) {
|
||||
const time = (percent / 100) * duration.value;
|
||||
seek(time);
|
||||
}
|
||||
};
|
||||
|
||||
const skip = (seconds) => {
|
||||
if (audioElement.value) {
|
||||
const newTime = Math.max(0, Math.min(duration.value, currentTime.value + seconds));
|
||||
seek(newTime);
|
||||
}
|
||||
};
|
||||
|
||||
const setPlaybackRate = (rate) => {
|
||||
playbackRate.value = rate;
|
||||
if (audioElement.value) {
|
||||
audioElement.value.playbackRate = rate;
|
||||
}
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
if (audioElement.value) {
|
||||
audioElement.value.pause();
|
||||
audioElement.value.currentTime = 0;
|
||||
}
|
||||
isPlaying.value = false;
|
||||
currentTime.value = 0;
|
||||
duration.value = 0;
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
isPlaying,
|
||||
currentTime,
|
||||
duration,
|
||||
playbackRate,
|
||||
audioElement,
|
||||
|
||||
// Computed
|
||||
progress,
|
||||
formattedCurrentTime,
|
||||
formattedDuration,
|
||||
|
||||
// Methods
|
||||
initPlayer,
|
||||
play,
|
||||
pause,
|
||||
togglePlayPause,
|
||||
seek,
|
||||
seekPercent,
|
||||
skip,
|
||||
setPlaybackRate,
|
||||
reset
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user