Skip to content

Commit 2be3755

Browse files
committed
Update AudioPlayer.mjs
1 parent 9d1b785 commit 2be3755

File tree

1 file changed

+93
-88
lines changed

1 file changed

+93
-88
lines changed

MyApp/wwwroot/pages/podcasts/AudioPlayer.mjs

Lines changed: 93 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ const ForwardIcon = {
1313
const ForwardButton = {
1414
components: { ForwardIcon },
1515
template: `
16-
<button type="button"
17-
class="group relative rounded-full focus:outline-none"
18-
@click="player.seekBy(amount ?? 10)" :aria-label="'Fast-forward ' + (amount ?? 10) + ' seconds'">
19-
<div class="absolute -inset-4 -left-2 md:hidden" />
20-
<ForwardIcon class="h-6 w-6 stroke-slate-500 group-hover:stroke-slate-700" />
21-
</button>`,
16+
<button type="button"
17+
class="group relative rounded-full focus:outline-none"
18+
@click="player.seekBy(amount ?? 10)" :aria-label="'Fast-forward ' + (amount ?? 10) + ' seconds'">
19+
<div class="absolute -inset-4 -left-2 md:hidden" />
20+
<ForwardIcon class="h-6 w-6 stroke-slate-500 group-hover:stroke-slate-700" />
21+
</button>`,
2222
props: { player:Object, amount:Number },
2323
}
2424

2525
const MuteIcon = {
2626
template:`
27-
<svg aria-hidden="true" viewBox="0 0 24 24" stroke-width="2" stroke-line-cap="round" stroke-line-join="round">
27+
<svg aria-hidden="true" viewBox="0 0 24 24" stroke-width="2" stroke-line-cap="round" stroke-line-join="round">
2828
<template v-if="muted">
2929
<path d="M12 6L8 10H6C5.44772 10 5 10.4477 5 11V13C5 13.5523 5.44772 14 6 14H8L12 18V6Z" />
3030
<path d="M16 10L19 13" fill="none" />
@@ -35,19 +35,19 @@ const MuteIcon = {
3535
<path d="M17 7C17 7 19 9 19 12C19 15 17 17 17 17" fill="none" />
3636
<path d="M15.5 10.5C15.5 10.5 16 10.9998 16 11.9999C16 13 15.5 13.5 15.5 13.5" fill="none" />
3737
</template>
38-
</svg>`,
38+
</svg>`,
3939
props: { muted:Boolean }
4040
}
4141
const MuteButton = {
4242
components: { MuteIcon },
4343
template:`
44-
<button type="button" :aria-label="player.muted ? 'Unmute' : 'Mute'"
45-
class="group relative rounded-md hover:bg-slate-100 dark:hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 md:order-none"
44+
<button type="button" :aria-label="player.muted ? 'Unmute' : 'Mute'"
45+
class="group relative rounded-md hover:bg-slate-100 dark:hover:bg-slate-800 md:order-none focus:outline-none focus:ring-2 focus:ring-slate-400 dark:focus:ring-slate-700 focus:ring-offset-2 ring-offset-slate-400 dark:ring-offset-slate-700"
4646
@click="player.toggleMute()">
47-
<div class="absolute -inset-4 md:hidden" />
48-
<MuteIcon :muted="player.muted"
49-
class="h-6 w-6 fill-slate-500 stroke-slate-500 group-hover:fill-slate-700 group-hover:stroke-slate-700" />
50-
</button>
47+
<div class="absolute -inset-4 md:hidden" />
48+
<MuteIcon :muted="player.muted"
49+
class="h-6 w-6 fill-slate-500 dark:fill-slate-400 stroke-slate-500 dark:stroke-slate-400 group-hover:fill-slate-700 dark:group-hover:fill-slate-300 group-hover:stroke-slate-700 dark:group-hover:stroke-slate-300" />
50+
</button>
5151
`,
5252
props: { player:Object },
5353
}
@@ -99,13 +99,13 @@ const playbackRates = [
9999
]
100100
const PlaybackRateButton = {
101101
template:`
102-
<button type="button"
103-
class="relative flex h-6 w-6 items-center justify-center rounded-md text-slate-500 dark:text-slate-400 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-700 dark:hover:text-slate-200 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2"
104-
@click="nextPlaybackRate()"
105-
aria-label="Playback rate">
106-
<div class="absolute -inset-4 md:hidden"></div>
107-
<component :is="playbackRate.icon" class="h-4 w-4" />
108-
</button>
102+
<button type="button"
103+
class="relative flex h-6 w-6 items-center justify-center rounded-md text-slate-500 hover:bg-slate-100 dark:hover:bg-slate-800 hover:text-slate-700 dark:hover:text-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-400 dark:focus:ring-slate-700 focus:ring-offset-2 ring-offset-slate-400 dark:ring-offset-slate-700"
104+
@click="nextPlaybackRate()"
105+
aria-label="Playback rate">
106+
<div class="absolute -inset-4 md:hidden"></div>
107+
<component :is="playbackRate.icon" class="h-4 w-4" />
108+
</button>
109109
`,
110110
props: { player:Object },
111111
setup(props) {
@@ -123,17 +123,17 @@ const PlaybackRateButton = {
123123

124124
const PlayButton = {
125125
template:`
126-
<button type="button" :aria-label="player.isPlaying ? 'Pause' : 'Play'"
126+
<button type="button" :aria-label="player.isPlaying ? 'Pause' : 'Play'"
127127
class="group relative flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-slate-700 dark:bg-slate-200 hover:bg-slate-900 dark:hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-slate-700 dark:focus:ring-slate-200 focus:ring-offset-2 dark:ring-offset-black md:h-14 md:w-14"
128128
@click="player.toggle()">
129-
<div class="absolute -inset-3 md:hidden" />
130-
<svg v-if="player.isPlaying" viewBox="0 0 36 36" aria-hidden="true" class="h-5 w-5 fill-white dark:fill-black group-active:fill-white/80 dark:group-active:fill-black/80 md:h-7 md:w-7">
131-
<path d="M8.5 4C7.67157 4 7 4.67157 7 5.5V30.5C7 31.3284 7.67157 32 8.5 32H11.5C12.3284 32 13 31.3284 13 30.5V5.5C13 4.67157 12.3284 4 11.5 4H8.5ZM24.5 4C23.6716 4 23 4.67157 23 5.5V30.5C23 31.3284 23.6716 32 24.5 32H27.5C28.3284 32 29 31.3284 29 30.5V5.5C29 4.67157 28.3284 4 27.5 4H24.5Z" />
132-
</svg>
133-
<svg v-else viewBox="0 0 36 36" aria-hidden="true" class="h-5 w-5 fill-white dark:fill-black group-active:fill-white/80 dark:group-active:fill-black/80 md:h-7 md:w-7">
134-
<path d="M33.75 16.701C34.75 17.2783 34.75 18.7217 33.75 19.299L11.25 32.2894C10.25 32.8668 9 32.1451 9 30.9904L9 5.00962C9 3.85491 10.25 3.13323 11.25 3.71058L33.75 16.701Z" />
135-
</svg>
136-
</button>
129+
<div class="absolute -inset-3 md:hidden" />
130+
<svg v-if="player.isPlaying" viewBox="0 0 36 36" aria-hidden="true" class="h-5 w-5 fill-white dark:fill-black group-active:fill-white/80 dark:group-active:fill-black/80 md:h-7 md:w-7">
131+
<path d="M8.5 4C7.67157 4 7 4.67157 7 5.5V30.5C7 31.3284 7.67157 32 8.5 32H11.5C12.3284 32 13 31.3284 13 30.5V5.5C13 4.67157 12.3284 4 11.5 4H8.5ZM24.5 4C23.6716 4 23 4.67157 23 5.5V30.5C23 31.3284 23.6716 32 24.5 32H27.5C28.3284 32 29 31.3284 29 30.5V5.5C29 4.67157 28.3284 4 27.5 4H24.5Z" />
132+
</svg>
133+
<svg v-else viewBox="0 0 36 36" aria-hidden="true" class="h-5 w-5 fill-white dark:fill-black group-active:fill-white/80 dark:group-active:fill-black/80 md:h-7 md:w-7">
134+
<path d="M33.75 16.701C34.75 17.2783 34.75 18.7217 33.75 19.299L11.25 32.2894C10.25 32.8668 9 32.1451 9 30.9904L9 5.00962C9 3.85491 10.25 3.13323 11.25 3.71058L33.75 16.701Z" />
135+
</svg>
136+
</button>
137137
`,
138138
props: { player:Object },
139139
}
@@ -149,37 +149,37 @@ const RewindIcon = {
149149
const RewindButton = {
150150
components: { RewindIcon },
151151
template:`
152-
<button type="button"
152+
<button type="button"
153153
class="group relative rounded-full focus:outline-none"
154154
@click="player.seekBy(-(amount??10))"
155155
:aria-label="'Rewind ' + (amount??10) + ' seconds'">
156-
<div class="absolute -inset-4 -right-2 md:hidden" />
157-
<RewindIcon class="h-6 w-6 stroke-slate-500 group-hover:stroke-slate-700" />
158-
</button>`,
156+
<div class="absolute -inset-4 -right-2 md:hidden" />
157+
<RewindIcon class="h-6 w-6 stroke-slate-500 group-hover:stroke-slate-700" />
158+
</button>`,
159159
props: { player:Object, amount:Number },
160160
}
161161

162162
const Slider = {
163163
template:`
164164
<div class="w-full flex items-center">
165165
<div ref="sliderRef"
166-
class="relative flex-grow h-2 bg-gray-200 dark:bg-gray-700 rounded-full cursor-pointer"
167-
@click="handleClick"
168-
@mousedown="startDrag"
169-
@mousemove="handleDrag"
170-
@mouseup="stopDrag"
171-
@mouseleave="stopDrag">
172-
<div class="absolute top-0 left-0 h-full bg-blue-500 rounded-full"
173-
:style="{ width: progress + '%' }"></div>
166+
class="relative flex-grow h-2 bg-gray-200 dark:bg-gray-700 rounded-full cursor-pointer"
167+
@click="handleClick"
168+
@mousedown="startDrag"
169+
@mousemove="handleDrag"
170+
@mouseup="stopDrag"
171+
@mouseleave="stopDrag">
172+
<div class="absolute top-0 left-0 h-full bg-blue-500 rounded-full"
173+
:style="{ width: progress + '%' }"></div>
174174
<div class="absolute top-1/2 -mt-2 w-4 h-4 bg-white dark:bg-black border-2 border-blue-500 rounded-full shadow"
175-
:style="{ left: 'calc(' + progress + '% - 0.5rem)' }"></div>
175+
:style="{ left: 'calc(' + progress + '% - 0.5rem)' }"></div>
176176
</div>
177177
<div class="hidden ml-2 items-center gap-2 md:flex whitespace-nowrap">
178-
<span class="hidden rounded-md px-1 py-0.5 font-mono text-sm leading-6 md:block text-slate-500 dark:text-slate-400">{{ formatTime(currentTime) }}</span>
179-
<span class="text-sm leading-6 text-slate-300 dark:text-slate-600" aria-hidden="true">/</span>
180-
<span class="hidden rounded-md px-1 py-0.5 font-mono text-sm leading-6 text-slate-500 dark:text-slate-400 md:block">{{ formatTime(duration) }}</span>
181-
</div>
182-
</div>
178+
<span class="hidden rounded-md px-1 py-0.5 font-mono text-sm leading-6 md:block text-slate-500 dark:text-slate-400">{{ formatTime(currentTime) }}</span>
179+
<span class="text-sm leading-6 text-slate-300 dark:text-slate-600" aria-hidden="true">/</span>
180+
<span class="hidden rounded-md px-1 py-0.5 font-mono text-sm leading-6 text-slate-500 dark:text-slate-400 md:block">{{ formatTime(duration) }}</span>
181+
</div>
182+
</div>
183183
`,
184184
emits: ['update:currentTime'],
185185
props: {
@@ -253,46 +253,50 @@ const AudioPlayer = {
253253
Slider,
254254
},
255255
template:`
256-
<div v-if="src" :class="v.cls">
257-
<audio ref="refPlayer"
258-
@play="onPlay()" @pause="onPause()"
259-
@timeupdate="onTimeUpdate(Math.floor($event.currentTarget.currentTime))"
260-
@durationchange="onDurationChange(Math.floor($event.currentTarget.duration))"
261-
:muted="muted"
262-
/>
263-
<div class="hidden md:block">
256+
<div v-if="src" :class="v.cls">
257+
<button v-if="showClose" type="button" @click="$emit('close')" title="Close Audio Player">
258+
<svg class="size-4 absolute top-1 right-1 text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>
259+
</button>
260+
<audio ref="refPlayer"
261+
@play="onPlay()" @pause="onPause()"
262+
@timeupdate="onTimeUpdate(Math.floor($event.currentTarget.currentTime))"
263+
@durationchange="onDurationChange(Math.floor($event.currentTarget.duration))"
264+
:muted="muted"
265+
/>
266+
<div class="hidden md:block">
267+
<PlayButton :player="player"/>
268+
</div>
269+
<div :class="v.innerCls">
270+
<a :href="'/podcasts/' + id"
271+
class="truncate text-center text-sm font-bold leading-6 md:text-left"
272+
:title="title">
273+
{{title}}
274+
</a>
275+
<div :class="v.controlsCls">
276+
<div :class="v.startControlsCls">
277+
<MuteButton :player="player"/>
278+
</div>
279+
<div :class="v.midControlsCls">
280+
<RewindButton :player="player"/>
281+
<div class="md:hidden">
264282
<PlayButton :player="player"/>
283+
</div>
284+
<ForwardButton :player="player"/>
265285
</div>
266-
<div :class="v.innerCls">
267-
<a :href="'/podcasts/' + id"
268-
class="truncate text-center text-sm font-bold leading-6 md:text-left"
269-
:title="title">
270-
{{title}}
271-
</a>
272-
<div :class="v.controlsCls">
273-
<div :class="v.startControlsCls">
274-
<MuteButton :player="player"/>
275-
</div>
276-
<div :class="v.midControlsCls">
277-
<RewindButton :player="player"/>
278-
<div class="md:hidden">
279-
<PlayButton :player="player"/>
280-
</div>
281-
<ForwardButton :player="player"/>
282-
</div>
283-
<Slider :currentTime="currentTime" :duration="duration" @update:currentTime="player.currentTime=$event" />
284-
<div :class="v.endControlsCls">
285-
<div class="flex items-center">
286-
<PlaybackRateButton :player="player"/>
287-
</div>
288-
<div class="hidden items-center md:flex">
289-
<MuteButton :player="player"/>
290-
</div>
291-
</div>
292-
</div>
286+
<Slider :currentTime="currentTime" :duration="duration" @update:currentTime="player.currentTime=$event" />
287+
<div :class="v.endControlsCls">
288+
<div class="flex items-center">
289+
<PlaybackRateButton :player="player"/>
290+
</div>
291+
<div class="hidden items-center md:flex">
292+
<MuteButton :player="player"/>
293+
</div>
293294
</div>
294-
</div>
295+
</div>
296+
</div>
297+
</div>
295298
`,
299+
emits: ['close'],
296300
props: {
297301
bus: Object,
298302
id: String,
@@ -303,9 +307,10 @@ const AudioPlayer = {
303307
autoPlay: Boolean,
304308
variant: String,
305309
beaconUrl: String,
306-
cls: {
310+
showClose: Boolean,
311+
cls: {
307312
type: String,
308-
default: 'flex items-center gap-6 bg-white/90 dark:bg-black/90 px-4 py-4 shadow shadow-slate-200/80 dark:shadow-slate-700/80 ring-1 ring-slate-900/5 dark:ring-slate-50/5 backdrop-blur-sm md:px-6'
313+
default: 'flex items-center gap-6 bg-white/90 dark:bg-black/70 px-4 py-4 shadow shadow-slate-200/80 dark:shadow-slate-700/80 ring-1 ring-slate-900/5 dark:ring-slate-50/5 backdrop-blur-sm md:px-6'
309314
},
310315
innerCls: {
311316
type: String,
@@ -375,7 +380,7 @@ const AudioPlayer = {
375380
function onDurationChange(value) {
376381
duration.value = value
377382
}
378-
383+
379384
const player = globalThis.player = {
380385
get url() { return props.url },
381386
get id() { return props.id },
@@ -436,7 +441,7 @@ const AudioPlayer = {
436441
})
437442
onUnmounted(() => sub?.unsubscribe())
438443
// console.log('AudioPlayer.mjs', globalThis.player)
439-
444+
440445
return {
441446
v,
442447
refPlayer,

0 commit comments

Comments
 (0)