2020-02-16 18:30:00 +00:00
|
|
|
import Vue from 'vue'
|
2020-06-11 00:21:31 +00:00
|
|
|
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
|
2020-08-18 18:32:01 +00:00
|
|
|
import { mapActions } from 'vuex'
|
2020-02-16 18:30:00 +00:00
|
|
|
|
|
|
|
export default Vue.extend({
|
|
|
|
name: 'FtListVideo',
|
2020-06-11 00:21:31 +00:00
|
|
|
components: {
|
|
|
|
'ft-icon-button': FtIconButton
|
|
|
|
},
|
2020-02-16 18:30:00 +00:00
|
|
|
props: {
|
|
|
|
data: {
|
|
|
|
type: Object,
|
|
|
|
required: true
|
|
|
|
},
|
2020-05-17 20:12:58 +00:00
|
|
|
playlistId: {
|
|
|
|
type: String,
|
|
|
|
default: null
|
|
|
|
},
|
2020-02-16 18:30:00 +00:00
|
|
|
forceListType: {
|
|
|
|
type: String,
|
|
|
|
default: null
|
2020-06-23 15:47:19 +00:00
|
|
|
},
|
|
|
|
appearance: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
2020-02-16 18:30:00 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
data: function () {
|
|
|
|
return {
|
|
|
|
id: '',
|
|
|
|
title: '',
|
|
|
|
channelName: '',
|
|
|
|
channelId: '',
|
|
|
|
viewCount: 0,
|
2020-08-12 03:26:49 +00:00
|
|
|
parsedViewCount: '',
|
2020-02-16 18:30:00 +00:00
|
|
|
uploadedTime: '',
|
|
|
|
duration: '',
|
|
|
|
description: '',
|
|
|
|
watched: false,
|
2020-08-20 02:39:44 +00:00
|
|
|
watchProgress: 0,
|
|
|
|
publishedText: '',
|
2020-02-16 18:30:00 +00:00
|
|
|
isLive: false,
|
|
|
|
isFavorited: false,
|
2020-10-09 01:53:34 +00:00
|
|
|
isUpcoming: false,
|
2020-06-11 00:21:31 +00:00
|
|
|
hideViews: false,
|
|
|
|
optionsValues: [
|
2020-08-20 02:39:44 +00:00
|
|
|
'history',
|
2020-06-11 00:21:31 +00:00
|
|
|
'openYoutube',
|
|
|
|
'copyYoutube',
|
|
|
|
'openYoutubeEmbed',
|
|
|
|
'copyYoutubeEmbed',
|
|
|
|
'openInvidious',
|
2020-10-23 08:50:33 +00:00
|
|
|
'copyInvidious',
|
|
|
|
'openYoutubeChannel',
|
2020-10-23 10:51:39 +00:00
|
|
|
'copyYoutubeChannel',
|
|
|
|
'openInvidiousChannel',
|
|
|
|
'copyInvidiousChannel'
|
2020-06-11 00:21:31 +00:00
|
|
|
]
|
2020-02-16 18:30:00 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
2020-06-11 00:21:31 +00:00
|
|
|
usingElectron: function () {
|
|
|
|
return this.$store.getters.getUsingElectron
|
|
|
|
},
|
|
|
|
|
2020-08-20 02:39:44 +00:00
|
|
|
historyCache: function () {
|
|
|
|
return this.$store.getters.getHistoryCache
|
|
|
|
},
|
|
|
|
|
2020-02-16 18:30:00 +00:00
|
|
|
listType: function () {
|
|
|
|
return this.$store.getters.getListType
|
|
|
|
},
|
|
|
|
|
2020-02-27 03:10:56 +00:00
|
|
|
thumbnailPreference: function () {
|
|
|
|
return this.$store.getters.getThumbnailPreference
|
2020-05-17 20:12:58 +00:00
|
|
|
},
|
|
|
|
|
2020-06-03 02:27:55 +00:00
|
|
|
backendPreference: function () {
|
|
|
|
return this.$store.getters.getBackendPreference
|
|
|
|
},
|
|
|
|
|
|
|
|
invidiousInstance: function () {
|
|
|
|
return this.$store.getters.getInvidiousInstance
|
|
|
|
},
|
|
|
|
|
2020-08-20 02:39:44 +00:00
|
|
|
inHistory: function () {
|
|
|
|
// When in the history page, showing relative dates isn't very useful.
|
|
|
|
// We want to show the exact date instead
|
|
|
|
return this.$router.currentRoute.name === 'history'
|
|
|
|
},
|
|
|
|
|
2020-06-11 00:21:31 +00:00
|
|
|
invidiousUrl: function () {
|
|
|
|
return `${this.invidiousInstance}/watch?v=${this.id}`
|
|
|
|
},
|
|
|
|
|
2020-10-23 10:51:39 +00:00
|
|
|
invidiousChannelUrl: function () {
|
|
|
|
return `${this.invidiousInstance}/channel/${this.channelId}`
|
|
|
|
},
|
|
|
|
|
2020-06-11 00:21:31 +00:00
|
|
|
youtubeUrl: function () {
|
|
|
|
return `https://www.youtube.com/watch?v=${this.id}`
|
|
|
|
},
|
|
|
|
|
2020-10-19 14:11:50 +00:00
|
|
|
youtubeShareUrl: function () {
|
|
|
|
return `https://youtu.be/${this.id}`
|
|
|
|
},
|
|
|
|
|
2020-10-23 08:50:33 +00:00
|
|
|
youtubeChannelUrl: function () {
|
|
|
|
return `https://youtube.com/channel/${this.channelId}`
|
|
|
|
},
|
|
|
|
|
2020-06-11 00:21:31 +00:00
|
|
|
youtubeEmbedUrl: function () {
|
|
|
|
return `https://www.youtube-nocookie.com/embed/${this.id}`
|
|
|
|
},
|
|
|
|
|
2020-08-20 02:39:44 +00:00
|
|
|
progressPercentage: function () {
|
|
|
|
return (this.watchProgress / this.data.lengthSeconds) * 100
|
|
|
|
},
|
|
|
|
|
2020-08-12 03:26:49 +00:00
|
|
|
optionsNames: function () {
|
2020-08-20 02:39:44 +00:00
|
|
|
const names = [
|
2020-08-12 03:26:49 +00:00
|
|
|
this.$t('Video.Open in YouTube'),
|
|
|
|
this.$t('Video.Copy YouTube Link'),
|
|
|
|
this.$t('Video.Open YouTube Embedded Player'),
|
|
|
|
this.$t('Video.Copy YouTube Embedded Player Link'),
|
|
|
|
this.$t('Video.Open in Invidious'),
|
2020-10-23 08:50:33 +00:00
|
|
|
this.$t('Video.Copy Invidious Link'),
|
|
|
|
this.$t('Video.Open Channel in YouTube'),
|
2020-10-23 10:51:39 +00:00
|
|
|
this.$t('Video.Copy YouTube Channel Link'),
|
|
|
|
this.$t('Video.Open Channel in Invidious'),
|
|
|
|
this.$t('Video.Copy Invidious Channel Link')
|
2020-08-12 03:26:49 +00:00
|
|
|
]
|
2020-08-20 02:39:44 +00:00
|
|
|
|
|
|
|
if (this.watched) {
|
|
|
|
names.unshift(this.$t('Video.Remove From History'))
|
|
|
|
} else {
|
|
|
|
names.unshift(this.$t('Video.Mark As Watched'))
|
|
|
|
}
|
|
|
|
|
|
|
|
return names
|
2020-08-12 03:26:49 +00:00
|
|
|
},
|
|
|
|
|
2020-05-17 20:12:58 +00:00
|
|
|
thumbnail: function () {
|
2020-06-03 02:27:55 +00:00
|
|
|
let baseUrl
|
|
|
|
if (this.backendPreference === 'invidious') {
|
|
|
|
baseUrl = this.invidiousInstance
|
|
|
|
} else {
|
|
|
|
baseUrl = 'https://i.ytimg.com'
|
|
|
|
}
|
|
|
|
|
2020-05-17 20:12:58 +00:00
|
|
|
switch (this.thumbnailPreference) {
|
|
|
|
case 'start':
|
2020-06-03 02:27:55 +00:00
|
|
|
return `${baseUrl}/vi/${this.id}/mq1.jpg`
|
2020-05-17 20:12:58 +00:00
|
|
|
case 'middle':
|
2020-06-03 02:27:55 +00:00
|
|
|
return `${baseUrl}/vi/${this.id}/mq2.jpg`
|
2020-05-17 20:12:58 +00:00
|
|
|
case 'end':
|
2020-06-03 02:27:55 +00:00
|
|
|
return `${baseUrl}/vi/${this.id}/mq3.jpg`
|
2020-05-17 20:12:58 +00:00
|
|
|
default:
|
2020-06-03 02:27:55 +00:00
|
|
|
return `${baseUrl}/vi/${this.id}/mqdefault.jpg`
|
2020-05-17 20:12:58 +00:00
|
|
|
}
|
2020-10-06 02:27:32 +00:00
|
|
|
},
|
|
|
|
hideVideoViews: function () {
|
|
|
|
return this.$store.getters.getHideVideoViews
|
2020-02-16 18:30:00 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
mounted: function () {
|
2020-08-22 14:21:49 +00:00
|
|
|
this.parseVideoData()
|
2020-08-20 02:39:44 +00:00
|
|
|
this.checkIfWatched()
|
2020-02-16 18:30:00 +00:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
toggleSave: function () {
|
|
|
|
console.log('TODO: ft-list-video method toggleSave')
|
2020-09-22 22:13:04 +00:00
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Saving videos are currently not available. Please wait for a future update')
|
|
|
|
})
|
2020-02-16 18:30:00 +00:00
|
|
|
},
|
|
|
|
|
2020-06-11 00:21:31 +00:00
|
|
|
handleOptionsClick: function (option) {
|
|
|
|
console.log('Handling share')
|
|
|
|
console.log(option)
|
|
|
|
|
|
|
|
switch (option) {
|
2020-08-20 02:39:44 +00:00
|
|
|
case 'history':
|
|
|
|
if (this.watched) {
|
|
|
|
this.removeFromWatched()
|
|
|
|
} else {
|
|
|
|
this.markAsWatched()
|
|
|
|
}
|
|
|
|
break
|
2020-06-11 00:21:31 +00:00
|
|
|
case 'copyYoutube':
|
2020-10-19 14:11:50 +00:00
|
|
|
navigator.clipboard.writeText(this.youtubeShareUrl)
|
2020-08-21 01:20:22 +00:00
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Share.YouTube URL copied to clipboard')
|
|
|
|
})
|
2020-06-11 00:21:31 +00:00
|
|
|
break
|
|
|
|
case 'openYoutube':
|
|
|
|
if (this.usingElectron) {
|
|
|
|
const shell = require('electron').shell
|
|
|
|
shell.openExternal(this.youtubeUrl)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case 'copyYoutubeEmbed':
|
|
|
|
navigator.clipboard.writeText(this.youtubeEmbedUrl)
|
2020-08-21 01:20:22 +00:00
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Share.YouTube Embed URL copied to clipboard')
|
|
|
|
})
|
2020-06-11 00:21:31 +00:00
|
|
|
break
|
|
|
|
case 'openYoutubeEmbed':
|
|
|
|
if (this.usingElectron) {
|
|
|
|
const shell = require('electron').shell
|
|
|
|
shell.openExternal(this.youtubeEmbedUrl)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case 'copyInvidious':
|
|
|
|
navigator.clipboard.writeText(this.invidiousUrl)
|
2020-08-21 01:20:22 +00:00
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Share.Invidious URL copied to clipboard')
|
|
|
|
})
|
2020-06-11 00:21:31 +00:00
|
|
|
break
|
|
|
|
case 'openInvidious':
|
|
|
|
if (this.usingElectron) {
|
|
|
|
console.log('using electron')
|
|
|
|
const shell = require('electron').shell
|
|
|
|
shell.openExternal(this.invidiousUrl)
|
|
|
|
}
|
|
|
|
break
|
2020-10-23 08:50:33 +00:00
|
|
|
case 'copyYoutubeChannel':
|
|
|
|
navigator.clipboard.writeText(this.youtubeChannelUrl)
|
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Share.YouTube Channel URL copied to clipboard')
|
|
|
|
})
|
|
|
|
break
|
|
|
|
case 'openYoutubeChannel':
|
|
|
|
if (this.usingElectron) {
|
|
|
|
const shell = require('electron').shell
|
|
|
|
shell.openExternal(this.youtubeChannelUrl)
|
|
|
|
}
|
|
|
|
break
|
2020-10-23 10:51:39 +00:00
|
|
|
case 'copyInvidiousChannel':
|
|
|
|
navigator.clipboard.writeText(this.invidiousChannelUrl)
|
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Share.Invidious Channel URL copied to clipboard')
|
|
|
|
})
|
|
|
|
break
|
|
|
|
case 'openInvidiousChannel':
|
|
|
|
if (this.usingElectron) {
|
|
|
|
const shell = require('electron').shell
|
|
|
|
shell.openExternal(this.invidiousChannelUrl)
|
|
|
|
}
|
|
|
|
break
|
2020-06-11 00:21:31 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-02-16 18:30:00 +00:00
|
|
|
// For Invidious data, as duration is sent in seconds
|
|
|
|
calculateVideoDuration: function (lengthSeconds) {
|
2020-08-25 14:18:14 +00:00
|
|
|
if (typeof lengthSeconds === 'string') {
|
|
|
|
return lengthSeconds
|
|
|
|
}
|
2020-09-25 02:35:13 +00:00
|
|
|
|
|
|
|
if (typeof lengthSeconds === 'undefined') {
|
|
|
|
return '0:00'
|
|
|
|
}
|
2020-02-16 18:30:00 +00:00
|
|
|
let durationText = ''
|
|
|
|
let time = lengthSeconds
|
|
|
|
let hours = 0
|
|
|
|
|
|
|
|
if (time >= 3600) {
|
|
|
|
hours = Math.floor(time / 3600)
|
|
|
|
time = time - hours * 3600
|
|
|
|
}
|
|
|
|
|
|
|
|
let minutes = Math.floor(time / 60)
|
|
|
|
let seconds = time - minutes * 60
|
|
|
|
|
|
|
|
if (seconds < 10) {
|
|
|
|
seconds = '0' + seconds
|
|
|
|
}
|
|
|
|
|
|
|
|
if (minutes < 10 && hours > 0) {
|
|
|
|
minutes = '0' + minutes
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hours > 0) {
|
|
|
|
durationText = hours + ':' + minutes + ':' + seconds
|
|
|
|
} else {
|
|
|
|
durationText = minutes + ':' + seconds
|
|
|
|
}
|
|
|
|
|
|
|
|
return durationText
|
|
|
|
},
|
|
|
|
|
2020-08-22 14:21:49 +00:00
|
|
|
parseVideoData: function () {
|
2020-02-16 18:30:00 +00:00
|
|
|
this.id = this.data.videoId
|
|
|
|
this.title = this.data.title
|
|
|
|
// this.thumbnail = this.data.videoThumbnails[4].url
|
2020-05-17 20:12:58 +00:00
|
|
|
|
2020-02-16 18:30:00 +00:00
|
|
|
this.channelName = this.data.author
|
|
|
|
this.channelId = this.data.authorId
|
|
|
|
this.duration = this.calculateVideoDuration(this.data.lengthSeconds)
|
|
|
|
this.description = this.data.description
|
2020-10-14 13:50:57 +00:00
|
|
|
this.isLive = this.data.liveNow || this.data.lengthSeconds === 'undefined'
|
2020-10-09 01:53:34 +00:00
|
|
|
this.isUpcoming = this.data.isUpcoming || this.data.premiere
|
2020-08-12 03:26:49 +00:00
|
|
|
this.viewCount = this.data.viewCount
|
2020-02-16 18:30:00 +00:00
|
|
|
|
2020-10-09 01:53:34 +00:00
|
|
|
if (typeof (this.data.premiereTimestamp) !== 'undefined') {
|
|
|
|
this.publishedText = new Date(this.data.premiereTimestamp * 1000).toLocaleString()
|
|
|
|
} else {
|
|
|
|
this.publishedText = this.data.publishedText
|
|
|
|
}
|
|
|
|
|
2020-10-02 11:55:02 +00:00
|
|
|
if (typeof (this.data.publishedText) !== 'undefined' && this.data.publishedText !== null && !this.isLive) {
|
2020-08-18 18:32:01 +00:00
|
|
|
// produces a string according to the template in the locales string
|
2020-08-18 19:37:43 +00:00
|
|
|
this.toLocalePublicationString({
|
2020-10-09 01:53:34 +00:00
|
|
|
publishText: this.publishedText,
|
2020-08-18 18:32:01 +00:00
|
|
|
templateString: this.$t('Video.Publicationtemplate'),
|
2020-08-18 19:37:43 +00:00
|
|
|
timeStrings: this.$t('Video.Published'),
|
|
|
|
liveStreamString: this.$t('Video.Watching'),
|
|
|
|
upcomingString: this.$t('Video.Published.Upcoming'),
|
2020-08-20 02:39:44 +00:00
|
|
|
isLive: this.isLive,
|
2020-10-09 01:53:34 +00:00
|
|
|
isUpcoming: this.isUpcoming,
|
2020-09-02 03:20:21 +00:00
|
|
|
isRSS: this.data.isRSS
|
2020-08-18 18:32:01 +00:00
|
|
|
}).then((data) => {
|
|
|
|
this.uploadedTime = data
|
|
|
|
}).catch((error) => {
|
|
|
|
console.error(error)
|
|
|
|
})
|
2020-02-16 18:30:00 +00:00
|
|
|
}
|
|
|
|
|
2020-10-06 02:27:32 +00:00
|
|
|
if (this.hideVideoViews) {
|
|
|
|
this.hideViews = true
|
|
|
|
} else if (typeof (this.data.viewCount) !== 'undefined' && this.data.viewCount !== null) {
|
2020-08-12 03:26:49 +00:00
|
|
|
this.parsedViewCount = this.data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
2020-02-16 18:30:00 +00:00
|
|
|
} else if (typeof (this.data.viewCountText) !== 'undefined') {
|
2020-08-12 03:26:49 +00:00
|
|
|
this.parsedViewCount = this.data.viewCountText.replace(' views', '')
|
2020-02-16 18:30:00 +00:00
|
|
|
} else {
|
|
|
|
this.hideViews = true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-08-20 02:39:44 +00:00
|
|
|
checkIfWatched: function () {
|
|
|
|
const historyIndex = this.historyCache.findIndex((video) => {
|
|
|
|
return video.videoId === this.id
|
|
|
|
})
|
|
|
|
|
|
|
|
if (historyIndex !== -1) {
|
|
|
|
this.watched = true
|
|
|
|
this.watchProgress = this.historyCache[historyIndex].watchProgress
|
|
|
|
|
|
|
|
if (this.historyCache[historyIndex].published !== '') {
|
|
|
|
const videoPublished = this.historyCache[historyIndex].published
|
|
|
|
const videoPublishedDate = new Date(videoPublished)
|
|
|
|
this.publishedText = videoPublishedDate.toLocaleDateString()
|
|
|
|
} else {
|
|
|
|
this.publishedText = ''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
markAsWatched: function () {
|
|
|
|
const videoData = {
|
|
|
|
videoId: this.id,
|
|
|
|
title: this.title,
|
|
|
|
author: this.channelName,
|
|
|
|
authorId: this.channelId,
|
|
|
|
published: '',
|
|
|
|
description: this.description,
|
|
|
|
viewCount: this.viewCount,
|
|
|
|
lengthSeconds: this.data.lengthSeconds,
|
|
|
|
watchProgress: 0,
|
|
|
|
timeWatched: new Date().getTime(),
|
|
|
|
isLive: false,
|
|
|
|
paid: false,
|
|
|
|
type: 'video'
|
|
|
|
}
|
|
|
|
|
|
|
|
this.updateHistory(videoData)
|
|
|
|
|
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Video.Video has been marked as watched')
|
|
|
|
})
|
|
|
|
|
|
|
|
this.watched = true
|
|
|
|
},
|
|
|
|
|
|
|
|
removeFromWatched: function () {
|
|
|
|
this.removeFromHistory(this.id)
|
|
|
|
|
|
|
|
this.showToast({
|
|
|
|
message: this.$t('Video.Video has been removed from your history')
|
|
|
|
})
|
|
|
|
|
|
|
|
this.watched = false
|
|
|
|
},
|
|
|
|
|
2020-08-18 18:32:01 +00:00
|
|
|
...mapActions([
|
2020-08-20 02:39:44 +00:00
|
|
|
'showToast',
|
|
|
|
'toLocalePublicationString',
|
|
|
|
'updateHistory',
|
|
|
|
'removeFromHistory'
|
2020-08-18 18:32:01 +00:00
|
|
|
])
|
2020-02-16 18:30:00 +00:00
|
|
|
}
|
|
|
|
})
|