diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js index d85c03d3..c64c4b5c 100644 --- a/src/renderer/components/data-settings/data-settings.js +++ b/src/renderer/components/data-settings/data-settings.js @@ -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', diff --git a/src/renderer/components/ft-profile-edit/ft-profile-edit.js b/src/renderer/components/ft-profile-edit/ft-profile-edit.js index 29544729..a2c02d0a 100644 --- a/src/renderer/components/ft-profile-edit/ft-profile-edit.js +++ b/src/renderer/components/ft-profile-edit/ft-profile-edit.js @@ -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' ]) } }) diff --git a/src/renderer/components/ft-video-player/ft-video-player.js b/src/renderer/components/ft-video-player/ft-video-player.js index 307146a4..e889964a 100644 --- a/src/renderer/components/ft-video-player/ft-video-player.js +++ b/src/renderer/components/ft-video-player/ft-video-player.js @@ -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', diff --git a/src/renderer/helpers/utils.js b/src/renderer/helpers/utils.js new file mode 100644 index 00000000..46fb3567 --- /dev/null +++ b/src/renderer/helpers/utils.js @@ -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 +} diff --git a/src/renderer/store/modules/profiles.js b/src/renderer/store/modules/profiles.js index 046f3224..7c189f55 100644 --- a/src/renderer/store/modules/profiles.js +++ b/src/renderer/store/modules/profiles.js @@ -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, diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js index e75f82a9..9e85e33d 100644 --- a/src/renderer/store/modules/utils.js +++ b/src/renderer/store/modules/utils.js @@ -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 diff --git a/src/renderer/views/ProfileEdit/ProfileEdit.js b/src/renderer/views/ProfileEdit/ProfileEdit.js index 1ffb531b..6034fd1b 100644 --- a/src/renderer/views/ProfileEdit/ProfileEdit.js +++ b/src/renderer/views/ProfileEdit/ProfileEdit.js @@ -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' ]) } }) diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 9c8f5f0c..8ac29f6b 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -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' ]), diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js index b6839345..f56ec2b0 100644 --- a/src/renderer/views/Watch/Watch.js +++ b/src/renderer/views/Watch/Watch.js @@ -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',