feat: chapters based on timecodes in description (fix #69)
Some checks failed
repod / nodejs (push) Waiting to run
repod / release (push) Waiting to run
repod / xml (push) Successful in 22s
repod / php (push) Has been cancelled

This commit is contained in:
Michel Roux 2024-11-12 21:43:38 +01:00
parent eb6a4b2d9b
commit e43adc79a1
2 changed files with 60 additions and 8 deletions

View File

@ -1,22 +1,41 @@
<template> <template>
<div v-sanitize="source" class="html" /> <div ref="html" v-sanitize="source" class="html" />
</template> </template>
<script lang="ts"> <script lang="ts">
import dompurify from 'dompurify' import dompurify from 'dompurify'
import linkifyHtml from 'linkify-html' import linkifyHtml from 'linkify-html'
import { mapActions } from 'pinia'
import { timeToSeconds } from '../../utils/time.ts'
import { usePlayer } from '../../store/player.ts'
export default { export default {
name: 'SafeHtml', name: 'SafeHtml',
directives: { directives: {
sanitize: { sanitize: {
mounted(el, binding) { mounted(el, binding) {
el.innerHTML = dompurify.sanitize( el.innerHTML = dompurify
linkifyHtml(binding.value, { .sanitize(
nl2br: true, linkifyHtml(binding.value, {
target: '_blank', nl2br: true,
}), target: '_blank',
) }),
)
.replace(
/(([0-9]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])/g,
(
match,
noop: string,
hours: string,
minutes: string,
seconds: string,
) =>
`<seekable time="${timeToSeconds(
parseInt(hours),
parseInt(minutes),
parseInt(seconds),
)}">${match}</seekable>`,
)
}, },
}, },
}, },
@ -26,11 +45,31 @@ export default {
required: true, required: true,
}, },
}, },
mounted() {
const seekables = (this.$refs.html as HTMLElement).querySelectorAll(
'seekable',
)
for (const seekable of seekables) {
seekable.addEventListener('click', (event) => {
this.seek(
parseInt(
(event.target as HTMLElement).getAttribute('time') || '',
),
)
this.play()
})
}
},
methods: {
...mapActions(usePlayer, ['play', 'seek']),
},
} }
</script> </script>
<style> <style>
.html a { .html a,
seekable {
cursor: pointer;
text-decoration: underline; text-decoration: underline;
} }
</style> </style>

View File

@ -51,3 +51,16 @@ export const durationToSeconds = (duration: string): number => {
seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0 seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0
return seconds return seconds
} }
/**
* Convert splitted time to seconds
* @param {number} hours The number of seconds
* @param {number} minutes The number of seconds
* @param {number} seconds The number of seconds
* @return {number}
*/
export const timeToSeconds = (
hours: number,
minutes: number,
seconds: number,
): number => hours * 3600 + minutes * 60 + seconds