Make timestamps clickable

Replaces timestamps in comments and description with links that set
current video timestamp when clicked.
This commit is contained in:
Mykyta Poturai 2020-09-19 19:19:58 +03:00
parent 49451a19a1
commit 7cb396fcce
9 changed files with 61 additions and 7 deletions

View File

@ -0,0 +1,26 @@
import Vue from 'vue'
export default Vue.extend({
name: 'FtTimestampCatcher',
props: {
inputHTML: {
type: String,
default: ''
}
},
methods: {
catchTimestampClick: function(event) {
const match = event.detail.match(/(\d+):(\d+):?(\d+)?/)
if (match[3] !== undefined) { // HH:MM:SS
const seconds = 3600 * Number(match[1]) + 60 * Number(match[2]) + Number(match[3])
this.$emit('timestampEvent', seconds)
} else { // MM:SS
const seconds = 60 * Number(match[1]) + Number(match[2])
this.$emit('timestampEvent', seconds)
}
},
detectTimestamps: function (input) {
return input.replaceAll(/(\d+(:\d+)+)/g, '<a href="#" onclick="this.dispatchEvent(new CustomEvent(\'timestampClicked\',{bubbles:true, detail:\'$1\'}))">$1</a>')
}
}
})

View File

@ -0,0 +1,9 @@
<template>
<p
@timestampClicked="catchTimestampClick"
v-html="detectTimestamps(inputHTML)"
/>
</template>
<script src="./ft-timestamp-catcher.js" />
<style scoped src="./ft-timestamp-catcher.css" />

View File

@ -3,12 +3,14 @@ import { mapActions } from 'vuex'
import FtCard from '../ft-card/ft-card.vue' import FtCard from '../ft-card/ft-card.vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtLoader from '../../components/ft-loader/ft-loader.vue'
import CommentScraper from 'yt-comment-scraper' import CommentScraper from 'yt-comment-scraper'
import FtTimestampCatcher from '../../components/ft-timestamp-catcher/ft-timestamp-catcher.vue'
export default Vue.extend({ export default Vue.extend({
name: 'WatchVideoComments', name: 'WatchVideoComments',
components: { components: {
'ft-card': FtCard, 'ft-card': FtCard,
'ft-loader': FtLoader 'ft-loader': FtLoader,
'ft-timestamp-catcher': FtTimestampCatcher
}, },
props: { props: {
id: { id: {
@ -39,6 +41,10 @@ export default Vue.extend({
} }
}, },
methods: { methods: {
onTimestamp: function(timestamp) {
this.$emit('timestampEvent', timestamp)
},
getCommentData: function () { getCommentData: function () {
this.isLoading = true this.isLoading = true
switch (this.backendPreference) { switch (this.backendPreference) {

View File

@ -46,9 +46,11 @@
{{ comment.time }} {{ comment.time }}
</span> </span>
</p> </p>
<p class="commentText"> <ft-timestamp-catcher
{{ comment.text }} class="commentText"
</p> :inputHTML="comment.text"
@timestampEvent="onTimestamp"
/>
<p class="commentLikeCount"> <p class="commentLikeCount">
<font-awesome-icon <font-awesome-icon
icon="thumbs-up" icon="thumbs-up"

View File

@ -1,11 +1,13 @@
import Vue from 'vue' import Vue from 'vue'
import FtCard from '../ft-card/ft-card.vue' import FtCard from '../ft-card/ft-card.vue'
import FtTimestampCatcher from '../ft-timestamp-catcher/ft-timestamp-catcher.vue'
import autolinker from 'autolinker' import autolinker from 'autolinker'
export default Vue.extend({ export default Vue.extend({
name: 'WatchVideoDescription', name: 'WatchVideoDescription',
components: { components: {
'ft-card': FtCard 'ft-card': FtCard,
'ft-timestamp-catcher': FtTimestampCatcher
}, },
props: { props: {
published: { published: {
@ -34,6 +36,9 @@ export default Vue.extend({
} }
}, },
methods: { methods: {
onTimestamp: function(timestamp) {
this.$emit('timestampEvent', timestamp)
},
parseDescriptionHtml: function (descriptionText) { parseDescriptionHtml: function (descriptionText) {
descriptionText = descriptionText.replace(/target="_blank"/g, '') descriptionText = descriptionText.replace(/target="_blank"/g, '')
descriptionText = descriptionText.replace(/\/redirect.+?(?=q=)/g, '') descriptionText = descriptionText.replace(/\/redirect.+?(?=q=)/g, '')

View File

@ -1,8 +1,9 @@
<template> <template>
<ft-card class="videoDescription"> <ft-card class="videoDescription">
<p <ft-timestamp-catcher
class="description" class="description"
v-html="shownDescription" :inputHTML="shownDescription"
@timestampEvent="onTimestamp"
/> />
</ft-card> </ft-card>
</template> </template>

View File

@ -166,6 +166,9 @@ export default Vue.extend({
} }
}, },
methods: { methods: {
changeTimestamp: function(timestamp) {
this.$refs.videoPlayer.player.currentTime(timestamp)
},
toggleTheatreMode: function() { toggleTheatreMode: function() {
this.useTheatreMode = !this.useTheatreMode this.useTheatreMode = !this.useTheatreMode
}, },

View File

@ -86,12 +86,14 @@
:description-html="videoDescriptionHtml" :description-html="videoDescriptionHtml"
class="watchVideo" class="watchVideo"
:class="{ theatreWatchVideo: useTheatreMode }" :class="{ theatreWatchVideo: useTheatreMode }"
@timestampEvent="changeTimestamp"
/> />
<watch-video-comments <watch-video-comments
v-if="!isLoading && !isLive" v-if="!isLoading && !isLive"
:id="videoId" :id="videoId"
class="watchVideo" class="watchVideo"
:class="{ theatreWatchVideo: useTheatreMode }" :class="{ theatreWatchVideo: useTheatreMode }"
@timestampEvent="changeTimestamp"
/> />
</div> </div>
<div class="sidebarArea"> <div class="sidebarArea">