chore: Adds playback speed for audio bubble
This commit is contained in:
@@ -76,7 +76,7 @@ const files = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col gap-2.5">
|
||||
<div v-if="imageAttachments.length" :class="classToApply">
|
||||
<ImageGrid :attachments="imageAttachments" type="image" />
|
||||
</div>
|
||||
@@ -86,7 +86,7 @@ const files = computed(() => {
|
||||
</div>
|
||||
|
||||
<div v-if="recordings.length" :class="classToApply">
|
||||
<div v-for="attachment in recordings" :key="attachment.id">
|
||||
<div v-for="attachment in recordings" :key="attachment.id" class="w-full">
|
||||
<AudioChip
|
||||
class="bg-n-alpha-3 dark:bg-n-alpha-2 text-n-slate-12"
|
||||
:attachment="attachment"
|
||||
|
||||
@@ -27,7 +27,7 @@ const remainingCount = computed(() =>
|
||||
|
||||
const gridClass = computed(() => {
|
||||
const count = props.attachments.length;
|
||||
const base = 'grid gap-1 w-full';
|
||||
const base = 'grid gap-2 w-full';
|
||||
|
||||
if (count === 1) return `${base} grid-cols-1`;
|
||||
|
||||
@@ -47,10 +47,10 @@ const itemClass = computed(() => index => {
|
||||
|
||||
if (count === 1) return `${base} w-full h-auto`;
|
||||
|
||||
if (count === 3 && index === 0) return `${base} row-span-2 h-[400px]`;
|
||||
if (count >= 5 && index === 0) return `${base} col-span-2 h-[200px]`;
|
||||
if (count === 3 && index === 0) return `${base} row-span-2 h-[392px]`;
|
||||
if (count >= 5 && index === 0) return `${base} col-span-2 h-[192px]`;
|
||||
|
||||
return count === 2 ? `${base} h-[400px]` : `${base} h-[200px]`;
|
||||
return count === 2 ? `${base} h-[400px]` : `${base} h-[192px]`;
|
||||
});
|
||||
|
||||
const shouldShowOverlay = computed(
|
||||
|
||||
@@ -25,16 +25,22 @@ const isPlaying = ref(false);
|
||||
const isMuted = ref(false);
|
||||
const currentTime = ref(0);
|
||||
const duration = ref(0);
|
||||
const playbackSpeed = ref(1);
|
||||
|
||||
const onLoadedMetadata = () => {
|
||||
duration.value = audioPlayer.value?.duration;
|
||||
};
|
||||
|
||||
const playbackSpeedLabel = computed(() => {
|
||||
return `${playbackSpeed.value}x`;
|
||||
});
|
||||
|
||||
// There maybe a chance that the audioPlayer ref is not available
|
||||
// When the onLoadMetadata is called, so we need to set the duration
|
||||
// value when the component is mounted
|
||||
onMounted(() => {
|
||||
duration.value = audioPlayer.value?.duration;
|
||||
audioPlayer.value.playbackRate = playbackSpeed.value;
|
||||
});
|
||||
|
||||
const formatTime = time => {
|
||||
@@ -71,6 +77,16 @@ const playOrPause = () => {
|
||||
const onEnd = () => {
|
||||
isPlaying.value = false;
|
||||
currentTime.value = 0;
|
||||
playbackSpeed.value = 1;
|
||||
audioPlayer.value.playbackRate = 1;
|
||||
};
|
||||
|
||||
const changePlaybackSpeed = () => {
|
||||
const speeds = [1, 1.5, 2];
|
||||
const currentIndex = speeds.indexOf(playbackSpeed.value);
|
||||
const nextIndex = (currentIndex + 1) % speeds.length;
|
||||
playbackSpeed.value = speeds[nextIndex];
|
||||
audioPlayer.value.playbackRate = playbackSpeed.value;
|
||||
};
|
||||
|
||||
const downloadAudio = async () => {
|
||||
@@ -105,7 +121,7 @@ const downloadAudio = async () => {
|
||||
<div class="tabular-nums text-xs">
|
||||
{{ formatTime(currentTime) }} / {{ formatTime(duration) }}
|
||||
</div>
|
||||
<div class="flex items-center px-2">
|
||||
<div class="flex-1 items-center flex px-2">
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
@@ -115,6 +131,14 @@ const downloadAudio = async () => {
|
||||
@input="seek"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="border-0 w-10 h-6 grid place-content-center bg-n-alpha-2 hover:bg-alpha-3 rounded-2xl"
|
||||
@click="changePlaybackSpeed"
|
||||
>
|
||||
<span class="text-xs text-n-slate-11 font-medium">
|
||||
{{ playbackSpeedLabel }}
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="p-0 border-0 size-8 grid place-content-center"
|
||||
@click="toggleMute"
|
||||
|
||||
Reference in New Issue
Block a user