Make timestamps clickable
Replaces timestamps in comments and description with links that set current video timestamp when clicked.
This commit is contained in:
parent
49451a19a1
commit
7cb396fcce
|
@ -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>')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -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" />
|
|
@ -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) {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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, '')
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue