Move calculateColorLuminance, calculatePublishedDate and buildVTTFileLocally out of the store (#2692)
This commit is contained in:
parent
7ca6440a88
commit
22a5062334
|
@ -11,6 +11,7 @@ import { MAIN_PROFILE_ID } from '../../../constants'
|
|||
import fs from 'fs'
|
||||
import { opmlToJSON } from 'opml-to-json'
|
||||
import ytch from 'yt-channel-info'
|
||||
import { calculateColorLuminance } from '../../helpers/utils'
|
||||
|
||||
// FIXME: Missing web logic branching
|
||||
|
||||
|
@ -1092,7 +1093,7 @@ export default Vue.extend({
|
|||
let index = convertedData.findIndex(p => p.name === profile.value)
|
||||
if (index === -1) { // profile doesn't exist yet
|
||||
const randomBgColor = await this.getRandomColor()
|
||||
const contrastyTextColor = await this.calculateColorLuminance(randomBgColor)
|
||||
const contrastyTextColor = calculateColorLuminance(randomBgColor)
|
||||
convertedData.push({
|
||||
name: profile.value,
|
||||
bgColor: randomBgColor,
|
||||
|
@ -1241,7 +1242,6 @@ export default Vue.extend({
|
|||
'compactHistory',
|
||||
'showToast',
|
||||
'getRandomColor',
|
||||
'calculateColorLuminance',
|
||||
'showOpenDialog',
|
||||
'readFileFromDialog',
|
||||
'showSaveDialog',
|
||||
|
|
|
@ -6,6 +6,7 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
|
|||
import FtInput from '../../components/ft-input/ft-input.vue'
|
||||
import FtButton from '../../components/ft-button/ft-button.vue'
|
||||
import { MAIN_PROFILE_ID } from '../../../constants'
|
||||
import { calculateColorLuminance } from '../../helpers/utils'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FtProfileEdit',
|
||||
|
@ -70,8 +71,8 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
watch: {
|
||||
profileBgColor: async function (val) {
|
||||
this.profileTextColor = await this.calculateColorLuminance(val)
|
||||
profileBgColor: function (val) {
|
||||
this.profileTextColor = calculateColorLuminance(val)
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
|
@ -163,8 +164,7 @@ export default Vue.extend({
|
|||
'updateProfile',
|
||||
'removeProfile',
|
||||
'updateDefaultProfile',
|
||||
'updateActiveProfile',
|
||||
'calculateColorLuminance'
|
||||
'updateActiveProfile'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -14,6 +14,7 @@ import 'videojs-http-source-selector'
|
|||
|
||||
import { IpcChannels } from '../../../constants'
|
||||
import { sponsorBlockSkipSegments } from '../../helpers/sponsorblock'
|
||||
import { calculateColorLuminance } from '../../helpers/utils'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'FtVideoPlayer',
|
||||
|
@ -1175,7 +1176,7 @@ export default Vue.extend({
|
|||
videojs.registerComponent('loopButton', loopButton)
|
||||
},
|
||||
|
||||
toggleVideoLoop: async function () {
|
||||
toggleVideoLoop: function () {
|
||||
const loopButton = document.getElementById('loopButton')
|
||||
|
||||
if (!this.player.loop()) {
|
||||
|
@ -1187,7 +1188,7 @@ export default Vue.extend({
|
|||
return color === currentTheme
|
||||
})
|
||||
|
||||
const themeTextColor = await this.calculateColorLuminance(colorValues[nameIndex])
|
||||
const themeTextColor = calculateColorLuminance(colorValues[nameIndex])
|
||||
|
||||
loopButton.classList.add('vjs-icon-loop-active')
|
||||
|
||||
|
@ -1923,7 +1924,6 @@ export default Vue.extend({
|
|||
},
|
||||
|
||||
...mapActions([
|
||||
'calculateColorLuminance',
|
||||
'updateDefaultCaptionSettings',
|
||||
'showToast',
|
||||
'parseScreenshotCustomFileName',
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
export function calculateColorLuminance(colorValue) {
|
||||
const cutHex = colorValue.substring(1, 7)
|
||||
const colorValueR = parseInt(cutHex.substring(0, 2), 16)
|
||||
const colorValueG = parseInt(cutHex.substring(2, 4), 16)
|
||||
const colorValueB = parseInt(cutHex.substring(4, 6), 16)
|
||||
|
||||
const luminance = (0.299 * colorValueR + 0.587 * colorValueG + 0.114 * colorValueB) / 255
|
||||
|
||||
if (luminance > 0.5) {
|
||||
return '#000000'
|
||||
} else {
|
||||
return '#FFFFFF'
|
||||
}
|
||||
}
|
||||
|
||||
export function calculatePublishedDate(publishedText) {
|
||||
const date = new Date()
|
||||
if (publishedText === 'Live') {
|
||||
return publishedText
|
||||
}
|
||||
|
||||
const textSplit = publishedText.split(' ')
|
||||
|
||||
if (textSplit[0].toLowerCase() === 'streamed') {
|
||||
textSplit.shift()
|
||||
}
|
||||
|
||||
const timeFrame = textSplit[1]
|
||||
const timeAmount = parseInt(textSplit[0])
|
||||
let timeSpan = null
|
||||
|
||||
if (timeFrame.indexOf('second') > -1) {
|
||||
timeSpan = timeAmount * 1000
|
||||
} else if (timeFrame.indexOf('minute') > -1) {
|
||||
timeSpan = timeAmount * 60000
|
||||
} else if (timeFrame.indexOf('hour') > -1) {
|
||||
timeSpan = timeAmount * 3600000
|
||||
} else if (timeFrame.indexOf('day') > -1) {
|
||||
timeSpan = timeAmount * 86400000
|
||||
} else if (timeFrame.indexOf('week') > -1) {
|
||||
timeSpan = timeAmount * 604800000
|
||||
} else if (timeFrame.indexOf('month') > -1) {
|
||||
timeSpan = timeAmount * 2592000000
|
||||
} else if (timeFrame.indexOf('year') > -1) {
|
||||
timeSpan = timeAmount * 31556952000
|
||||
}
|
||||
|
||||
return date.getTime() - timeSpan
|
||||
}
|
||||
|
||||
export function buildVTTFileLocally(storyboard) {
|
||||
let vttString = 'WEBVTT\n\n'
|
||||
// how many images are in one image
|
||||
const numberOfSubImagesPerImage = storyboard.sWidth * storyboard.sHeight
|
||||
// the number of storyboard images
|
||||
const numberOfImages = Math.ceil(storyboard.count / numberOfSubImagesPerImage)
|
||||
const intervalInSeconds = storyboard.interval / 1000
|
||||
let currentUrl = storyboard.url
|
||||
let startHours = 0
|
||||
let startMinutes = 0
|
||||
let startSeconds = 0
|
||||
let endHours = 0
|
||||
let endMinutes = 0
|
||||
let endSeconds = intervalInSeconds
|
||||
for (let i = 0; i < numberOfImages; i++) {
|
||||
let xCoord = 0
|
||||
let yCoord = 0
|
||||
for (let j = 0; j < numberOfSubImagesPerImage; j++) {
|
||||
// add the timestamp information
|
||||
const paddedStartHours = startHours.toString().padStart(2, '0')
|
||||
const paddedStartMinutes = startMinutes.toString().padStart(2, '0')
|
||||
const paddedStartSeconds = startSeconds.toString().padStart(2, '0')
|
||||
const paddedEndHours = endHours.toString().padStart(2, '0')
|
||||
const paddedEndMinutes = endMinutes.toString().padStart(2, '0')
|
||||
const paddedEndSeconds = endSeconds.toString().padStart(2, '0')
|
||||
vttString += `${paddedStartHours}:${paddedStartMinutes}:${paddedStartSeconds}.000 --> ${paddedEndHours}:${paddedEndMinutes}:${paddedEndSeconds}.000\n`
|
||||
// add the current image url as well as the x, y, width, height information
|
||||
vttString += currentUrl + `#xywh=${xCoord},${yCoord},${storyboard.width},${storyboard.height}\n\n`
|
||||
// update the variables
|
||||
startHours = endHours
|
||||
startMinutes = endMinutes
|
||||
startSeconds = endSeconds
|
||||
endSeconds += intervalInSeconds
|
||||
if (endSeconds >= 60) {
|
||||
endSeconds -= 60
|
||||
endMinutes += 1
|
||||
}
|
||||
if (endMinutes >= 60) {
|
||||
endMinutes -= 60
|
||||
endHours += 1
|
||||
}
|
||||
// x coordinate can only be smaller than the width of one subimage * the number of subimages per row
|
||||
xCoord = (xCoord + storyboard.width) % (storyboard.width * storyboard.sWidth)
|
||||
// only if the x coordinate is , so in a new row, we have to update the y coordinate
|
||||
if (xCoord === 0) {
|
||||
yCoord += storyboard.height
|
||||
}
|
||||
}
|
||||
// make sure that there is no value like M0 or M1 in the parameters that gets replaced
|
||||
currentUrl = currentUrl.replace('M' + i.toString() + '.jpg', 'M' + (i + 1).toString() + '.jpg')
|
||||
}
|
||||
return vttString
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { MAIN_PROFILE_ID } from '../../../constants'
|
||||
import { DBProfileHandlers } from '../../../datastores/handlers/index'
|
||||
import { calculateColorLuminance } from '../../helpers/utils'
|
||||
|
||||
const state = {
|
||||
profileList: [{
|
||||
|
@ -53,7 +54,7 @@ const actions = {
|
|||
if (profiles.length === 0) {
|
||||
// Create a default profile and persist it
|
||||
const randomColor = await dispatch('getRandomColor')
|
||||
const textColor = await dispatch('calculateColorLuminance', randomColor)
|
||||
const textColor = calculateColorLuminance(randomColor)
|
||||
const defaultProfile = {
|
||||
_id: MAIN_PROFILE_ID,
|
||||
name: defaultName,
|
||||
|
|
|
@ -563,57 +563,6 @@ const actions = {
|
|||
commit('setRegionValues', regionValues)
|
||||
},
|
||||
|
||||
calculateColorLuminance (_, colorValue) {
|
||||
const cutHex = colorValue.substring(1, 7)
|
||||
const colorValueR = parseInt(cutHex.substring(0, 2), 16)
|
||||
const colorValueG = parseInt(cutHex.substring(2, 4), 16)
|
||||
const colorValueB = parseInt(cutHex.substring(4, 6), 16)
|
||||
|
||||
const luminance = (0.299 * colorValueR + 0.587 * colorValueG + 0.114 * colorValueB) / 255
|
||||
|
||||
if (luminance > 0.5) {
|
||||
return '#000000'
|
||||
} else {
|
||||
return '#FFFFFF'
|
||||
}
|
||||
},
|
||||
|
||||
calculatePublishedDate(_, publishedText) {
|
||||
const date = new Date()
|
||||
|
||||
if (publishedText === 'Live') {
|
||||
return publishedText
|
||||
}
|
||||
|
||||
const textSplit = publishedText.split(' ')
|
||||
|
||||
if (textSplit[0].toLowerCase() === 'streamed') {
|
||||
textSplit.shift()
|
||||
}
|
||||
|
||||
const timeFrame = textSplit[1]
|
||||
const timeAmount = parseInt(textSplit[0])
|
||||
let timeSpan = null
|
||||
|
||||
if (timeFrame.indexOf('second') > -1) {
|
||||
timeSpan = timeAmount * 1000
|
||||
} else if (timeFrame.indexOf('minute') > -1) {
|
||||
timeSpan = timeAmount * 60000
|
||||
} else if (timeFrame.indexOf('hour') > -1) {
|
||||
timeSpan = timeAmount * 3600000
|
||||
} else if (timeFrame.indexOf('day') > -1) {
|
||||
timeSpan = timeAmount * 86400000
|
||||
} else if (timeFrame.indexOf('week') > -1) {
|
||||
timeSpan = timeAmount * 604800000
|
||||
} else if (timeFrame.indexOf('month') > -1) {
|
||||
timeSpan = timeAmount * 2592000000
|
||||
} else if (timeFrame.indexOf('year') > -1) {
|
||||
timeSpan = timeAmount * 31556952000
|
||||
}
|
||||
|
||||
return date.getTime() - timeSpan
|
||||
},
|
||||
|
||||
getVideoParamsFromUrl (_, url) {
|
||||
/** @type {URL} */
|
||||
let urlObject
|
||||
|
@ -855,86 +804,6 @@ const actions = {
|
|||
}
|
||||
},
|
||||
|
||||
padNumberWithLeadingZeros(_, payload) {
|
||||
let numberString = payload.number.toString()
|
||||
while (numberString.length < payload.length) {
|
||||
numberString = '0' + numberString
|
||||
}
|
||||
return numberString
|
||||
},
|
||||
|
||||
async buildVTTFileLocally ({ dispatch }, Storyboard) {
|
||||
let vttString = 'WEBVTT\n\n'
|
||||
// how many images are in one image
|
||||
const numberOfSubImagesPerImage = Storyboard.sWidth * Storyboard.sHeight
|
||||
// the number of storyboard images
|
||||
const numberOfImages = Math.ceil(Storyboard.count / numberOfSubImagesPerImage)
|
||||
const intervalInSeconds = Storyboard.interval / 1000
|
||||
let currentUrl = Storyboard.url
|
||||
let startHours = 0
|
||||
let startMinutes = 0
|
||||
let startSeconds = 0
|
||||
let endHours = 0
|
||||
let endMinutes = 0
|
||||
let endSeconds = intervalInSeconds
|
||||
for (let i = 0; i < numberOfImages; i++) {
|
||||
let xCoord = 0
|
||||
let yCoord = 0
|
||||
for (let j = 0; j < numberOfSubImagesPerImage; j++) {
|
||||
// add the timestamp information
|
||||
const paddedStartHours = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: startHours,
|
||||
length: 2
|
||||
})
|
||||
const paddedStartMinutes = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: startMinutes,
|
||||
length: 2
|
||||
})
|
||||
const paddedStartSeconds = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: startSeconds,
|
||||
length: 2
|
||||
})
|
||||
const paddedEndHours = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: endHours,
|
||||
length: 2
|
||||
})
|
||||
const paddedEndMinutes = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: endMinutes,
|
||||
length: 2
|
||||
})
|
||||
const paddedEndSeconds = await dispatch('padNumberWithLeadingZeros', {
|
||||
number: endSeconds,
|
||||
length: 2
|
||||
})
|
||||
vttString += `${paddedStartHours}:${paddedStartMinutes}:${paddedStartSeconds}.000 --> ${paddedEndHours}:${paddedEndMinutes}:${paddedEndSeconds}.000\n`
|
||||
// add the current image url as well as the x, y, width, height information
|
||||
vttString += currentUrl + `#xywh=${xCoord},${yCoord},${Storyboard.width},${Storyboard.height}\n\n`
|
||||
// update the variables
|
||||
startHours = endHours
|
||||
startMinutes = endMinutes
|
||||
startSeconds = endSeconds
|
||||
endSeconds += intervalInSeconds
|
||||
if (endSeconds >= 60) {
|
||||
endSeconds -= 60
|
||||
endMinutes += 1
|
||||
}
|
||||
if (endMinutes >= 60) {
|
||||
endMinutes -= 60
|
||||
endHours += 1
|
||||
}
|
||||
// x coordinate can only be smaller than the width of one subimage * the number of subimages per row
|
||||
xCoord = (xCoord + Storyboard.width) % (Storyboard.width * Storyboard.sWidth)
|
||||
// only if the x coordinate is , so in a new row, we have to update the y coordinate
|
||||
if (xCoord === 0) {
|
||||
yCoord += Storyboard.height
|
||||
}
|
||||
}
|
||||
// make sure that there is no value like M0 or M1 in the parameters that gets replaced
|
||||
currentUrl = currentUrl.replace('M' + i.toString() + '.jpg', 'M' + (i + 1).toString() + '.jpg')
|
||||
}
|
||||
return vttString
|
||||
},
|
||||
|
||||
toLocalePublicationString ({ dispatch }, payload) {
|
||||
if (payload.isLive) {
|
||||
return '0' + payload.liveStreamString
|
||||
|
|
|
@ -5,6 +5,7 @@ import FtProfileEdit from '../../components/ft-profile-edit/ft-profile-edit.vue'
|
|||
import FtProfileChannelList from '../../components/ft-profile-channel-list/ft-profile-channel-list.vue'
|
||||
import FtProfileFilterChannelsList from '../../components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.vue'
|
||||
import { MAIN_PROFILE_ID } from '../../../constants'
|
||||
import { calculateColorLuminance } from '../../helpers/utils'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'ProfileEdit',
|
||||
|
@ -60,7 +61,7 @@ export default Vue.extend({
|
|||
if (profileType === 'newProfile') {
|
||||
this.isNew = true
|
||||
const bgColor = await this.getRandomColor()
|
||||
const textColor = await this.calculateColorLuminance(bgColor)
|
||||
const textColor = calculateColorLuminance(bgColor)
|
||||
this.profile = {
|
||||
name: '',
|
||||
bgColor: bgColor,
|
||||
|
@ -88,8 +89,7 @@ export default Vue.extend({
|
|||
methods: {
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'getRandomColor',
|
||||
'calculateColorLuminance'
|
||||
'getRandomColor'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -11,6 +11,7 @@ import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubbl
|
|||
import ytch from 'yt-channel-info'
|
||||
import Parser from 'rss-parser'
|
||||
import { MAIN_PROFILE_ID } from '../../../constants'
|
||||
import { calculatePublishedDate } from '../../helpers/utils'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Subscriptions',
|
||||
|
@ -254,20 +255,20 @@ export default Vue.extend({
|
|||
|
||||
getChannelVideosLocalScraper: function (channel, failedAttempts = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ytch.getChannelVideos({ channelId: channel.id, sortBy: 'latest' }).then(async (response) => {
|
||||
ytch.getChannelVideos({ channelId: channel.id, sortBy: 'latest' }).then((response) => {
|
||||
if (response.alertMessage) {
|
||||
this.errorChannels.push(channel)
|
||||
resolve([])
|
||||
return
|
||||
}
|
||||
const videos = await Promise.all(response.items.map(async (video) => {
|
||||
const videos = response.items.map((video) => {
|
||||
if (video.liveNow) {
|
||||
video.publishedDate = new Date().getTime()
|
||||
} else {
|
||||
video.publishedDate = await this.calculatePublishedDate(video.publishedText)
|
||||
video.publishedDate = calculatePublishedDate(video.publishedText)
|
||||
}
|
||||
return video
|
||||
}))
|
||||
})
|
||||
|
||||
resolve(videos)
|
||||
}).catch((err) => {
|
||||
|
@ -497,7 +498,6 @@ export default Vue.extend({
|
|||
'updateShowProgressBar',
|
||||
'updateProfileSubscriptions',
|
||||
'updateAllSubscriptionsList',
|
||||
'calculatePublishedDate',
|
||||
'copyToClipboard'
|
||||
]),
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import WatchVideoPlaylist from '../../components/watch-video-playlist/watch-vide
|
|||
import WatchVideoRecommendations from '../../components/watch-video-recommendations/watch-video-recommendations.vue'
|
||||
import FtAgeRestricted from '../../components/ft-age-restricted/ft-age-restricted.vue'
|
||||
import i18n from '../../i18n/index'
|
||||
import { buildVTTFileLocally } from '../../helpers/utils'
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
|
@ -1347,8 +1348,8 @@ export default Vue.extend({
|
|||
})
|
||||
})
|
||||
// TODO: MAKE A VARIABLE WHICH CAN CHOOSE BETWEEN STORYBOARD ARRAY ELEMENTS
|
||||
this.buildVTTFileLocally(storyboardArray[1]).then(async (results) => {
|
||||
const userData = await this.getUserDataPath()
|
||||
const results = buildVTTFileLocally(storyboardArray[1])
|
||||
this.getUserDataPath().then((userData) => {
|
||||
let fileLocation
|
||||
let uriSchema
|
||||
|
||||
|
@ -1536,7 +1537,6 @@ export default Vue.extend({
|
|||
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'buildVTTFileLocally',
|
||||
'updateHistory',
|
||||
'updateWatchProgress',
|
||||
'getUserDataPath',
|
||||
|
|
Loading…
Reference in New Issue