Support for the 't' parameter in links (#1090)
This allows users to specify the timestamp of a video (in seconds) - by inputting a link into the search bar - by making use of the protocol link (freetube://), p.e in a browser
This commit is contained in:
parent
1452e361a1
commit
7eda649293
|
@ -284,10 +284,11 @@ export default Vue.extend({
|
|||
const v = this
|
||||
electron.ipcRenderer.on('openUrl', function (event, url) {
|
||||
if (url) {
|
||||
v.$store.dispatch('getVideoIdFromUrl', url).then((result) => {
|
||||
if (result) {
|
||||
v.$store.dispatch('getVideoParamsFromUrl', url).then(({ videoId, timestamp }) => {
|
||||
if (videoId) {
|
||||
v.$router.push({
|
||||
path: `/watch/${result}`
|
||||
path: `/watch/${videoId}`,
|
||||
query: timestamp ? { timestamp } : {}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -89,14 +89,15 @@ export default Vue.extend({
|
|||
searchInput.blur()
|
||||
}
|
||||
|
||||
const videoId = await this.$store.dispatch('getVideoIdFromUrl', query)
|
||||
const { videoId, timestamp } = await this.$store.dispatch('getVideoParamsFromUrl', query)
|
||||
const playlistId = await this.$store.dispatch('getPlaylistIdFromUrl', query)
|
||||
|
||||
console.log(playlistId)
|
||||
|
||||
if (videoId) {
|
||||
this.$router.push({
|
||||
path: `/watch/${videoId}`
|
||||
path: `/watch/${videoId}`,
|
||||
query: timestamp ? { timestamp } : {}
|
||||
})
|
||||
} else if (playlistId) {
|
||||
this.$router.push({
|
||||
|
|
|
@ -190,43 +190,53 @@ const actions = {
|
|||
return date.getTime() - timeSpan
|
||||
},
|
||||
|
||||
getVideoIdFromUrl (_, url) {
|
||||
getVideoParamsFromUrl (_, url) {
|
||||
/** @type {URL} */
|
||||
let urlObject
|
||||
const paramsObject = { videoId: null, timestamp: null }
|
||||
try {
|
||||
urlObject = new URL(url)
|
||||
} catch (e) {
|
||||
return false
|
||||
return paramsObject
|
||||
}
|
||||
|
||||
function extractParams(videoId) {
|
||||
paramsObject.videoId = videoId
|
||||
paramsObject.timestamp = urlObject.searchParams.get('t')
|
||||
}
|
||||
|
||||
const extractors = [
|
||||
// anything with /watch?v=
|
||||
function() {
|
||||
if (urlObject.pathname === '/watch' && urlObject.searchParams.has('v')) {
|
||||
return urlObject.searchParams.get('v')
|
||||
extractParams(urlObject.searchParams.get('v'))
|
||||
return paramsObject
|
||||
}
|
||||
},
|
||||
// youtu.be
|
||||
function() {
|
||||
if (urlObject.host === 'youtu.be' && urlObject.pathname.match(/^\/[A-Za-z0-9_-]+$/)) {
|
||||
return urlObject.pathname.slice(1)
|
||||
extractParams(urlObject.pathname.slice(1))
|
||||
return paramsObject
|
||||
}
|
||||
},
|
||||
// youtube.com/embed
|
||||
function() {
|
||||
if (urlObject.pathname.match(/^\/embed\/[A-Za-z0-9_-]+$/)) {
|
||||
return urlObject.pathname.replace('/embed/', '')
|
||||
extractParams(urlObject.pathname.replace('/embed/', ''))
|
||||
return paramsObject
|
||||
}
|
||||
},
|
||||
// cloudtube
|
||||
function() {
|
||||
if (urlObject.host.match(/^cadence\.(gq|moe)$/) && urlObject.pathname.match(/^\/cloudtube\/video\/[A-Za-z0-9_-]+$/)) {
|
||||
return urlObject.pathname.slice('/cloudtube/video/'.length)
|
||||
extractParams(urlObject.pathname.slice('/cloudtube/video/'.length))
|
||||
return paramsObject
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
return extractors.reduce((a, c) => a || c(), null) || false
|
||||
return extractors.reduce((a, c) => a || c(), null) || paramsObject
|
||||
},
|
||||
|
||||
getPlaylistIdFromUrl (_, url) {
|
||||
|
|
|
@ -74,6 +74,7 @@ export default Vue.extend({
|
|||
downloadLinks: [],
|
||||
watchingPlaylist: false,
|
||||
playlistId: '',
|
||||
timestamp: null,
|
||||
playNextTimeout: null
|
||||
}
|
||||
},
|
||||
|
@ -156,6 +157,7 @@ export default Vue.extend({
|
|||
this.downloadLinks = []
|
||||
|
||||
this.checkIfPlaylist()
|
||||
this.checkIfTimestamp()
|
||||
|
||||
switch (this.backendPreference) {
|
||||
case 'local':
|
||||
|
@ -177,6 +179,7 @@ export default Vue.extend({
|
|||
this.useTheatreMode = this.defaultTheatreMode
|
||||
|
||||
this.checkIfPlaylist()
|
||||
this.checkIfTimestamp()
|
||||
|
||||
if (!this.usingElectron) {
|
||||
this.getVideoInformationInvidious()
|
||||
|
@ -682,19 +685,33 @@ export default Vue.extend({
|
|||
|
||||
console.log(historyIndex)
|
||||
|
||||
if (historyIndex !== -1 && !this.isLive) {
|
||||
if (!this.isLive) {
|
||||
if (this.timestamp) {
|
||||
if (this.timestamp < 0) {
|
||||
this.$refs.videoPlayer.player.currentTime(0)
|
||||
} else if (this.timestamp > (this.videoLengthSeconds - 10)) {
|
||||
this.$refs.videoPlayer.player.currentTime(this.videoLengthSeconds - 10)
|
||||
} else {
|
||||
this.$refs.videoPlayer.player.currentTime(this.timestamp)
|
||||
}
|
||||
} else if (historyIndex !== -1) {
|
||||
const watchProgress = this.historyCache[historyIndex].watchProgress
|
||||
|
||||
if (watchProgress < (this.videoLengthSeconds - 10)) {
|
||||
this.$refs.videoPlayer.player.currentTime(watchProgress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.rememberHistory && historyIndex !== -1) {
|
||||
if (this.rememberHistory) {
|
||||
if (this.timestamp) {
|
||||
this.addToHistory(this.timestamp)
|
||||
} else if (historyIndex !== -1) {
|
||||
this.addToHistory(this.historyCache[historyIndex].watchProgress)
|
||||
} else if (this.rememberHistory) {
|
||||
} else {
|
||||
this.addToHistory(0)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
checkIfPlaylist: function () {
|
||||
|
@ -711,6 +728,16 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
|
||||
checkIfTimestamp: function () {
|
||||
if (typeof (this.$route.query) !== 'undefined') {
|
||||
try {
|
||||
this.timestamp = parseInt(this.$route.query.timestamp)
|
||||
} catch {
|
||||
this.timestamp = null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getLegacyFormats: function () {
|
||||
this.$store
|
||||
.dispatch('ytGetVideoInformation', this.videoId)
|
||||
|
|
Loading…
Reference in New Issue