Refactor: Erase `@electron/remote` references and other dangerous calls
The `remote` module is deprecated and `@electron/remote` is unnecessary, since the `ipcMain` and `ipcRenderer` can replace their functionality, providing better performance and better security. All other dangerous calls (mainly pulling main process constructs into the renderer process) have also been removed.
This commit is contained in:
parent
c9fd6385f4
commit
af0353ea32
|
@ -1,4 +1,7 @@
|
||||||
import { app, BrowserWindow, Menu, ipcMain, screen } from 'electron'
|
import {
|
||||||
|
app, BrowserWindow, dialog, Menu,
|
||||||
|
ipcMain, powerSaveBlocker, screen, shell
|
||||||
|
} from 'electron'
|
||||||
import Datastore from 'nedb'
|
import Datastore from 'nedb'
|
||||||
|
|
||||||
if (process.argv.includes('--version')) {
|
if (process.argv.includes('--version')) {
|
||||||
|
@ -9,8 +12,6 @@ if (process.argv.includes('--version')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function runApp() {
|
function runApp() {
|
||||||
require('@electron/remote/main').initialize()
|
|
||||||
|
|
||||||
require('electron-context-menu')({
|
require('electron-context-menu')({
|
||||||
showSearchWithGoogle: false,
|
showSearchWithGoogle: false,
|
||||||
showSaveImageAs: true,
|
showSaveImageAs: true,
|
||||||
|
@ -416,6 +417,38 @@ function runApp() {
|
||||||
mainWindow.webContents.session.setProxy({})
|
mainWindow.webContents.session.setProxy({})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.on('openExternalLink', (_, url) => {
|
||||||
|
if (typeof url === 'string') shell.openExternal(url)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('getLocale', () => {
|
||||||
|
return app.getLocale()
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('getUserDataPath', () => {
|
||||||
|
return app.getPath('userData')
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on('getUserDataPathSync', (event) => {
|
||||||
|
event.returnValue = app.getPath('userData')
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('showOpenDialog', async (_, options) => {
|
||||||
|
return await dialog.showOpenDialog(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('showSaveDialog', async (_, options) => {
|
||||||
|
return await dialog.showSaveDialog(options)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.on('stopPowerSaveBlocker', (_, id) => {
|
||||||
|
powerSaveBlocker.stop(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('startPowerSaveBlocker', (_, type) => {
|
||||||
|
return powerSaveBlocker.start(type)
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.on('createNewWindow', () => {
|
ipcMain.on('createNewWindow', () => {
|
||||||
createWindow(false, '', false)
|
createWindow(false, '', false)
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,23 +10,17 @@ import FtButton from './components/ft-button/ft-button.vue'
|
||||||
import FtToast from './components/ft-toast/ft-toast.vue'
|
import FtToast from './components/ft-toast/ft-toast.vue'
|
||||||
import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue'
|
import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import { app } from '@electron/remote'
|
|
||||||
import { markdown } from 'markdown'
|
import { markdown } from 'markdown'
|
||||||
import Parser from 'rss-parser'
|
import Parser from 'rss-parser'
|
||||||
|
|
||||||
let useElectron
|
let useElectron = false
|
||||||
let shell
|
let ipcRenderer = null
|
||||||
let electron
|
|
||||||
|
|
||||||
Vue.directive('observe-visibility', ObserveVisibility)
|
Vue.directive('observe-visibility', ObserveVisibility)
|
||||||
|
|
||||||
if (window && window.process && window.process.type === 'renderer') {
|
if (window && window.process && window.process.type === 'renderer') {
|
||||||
/* eslint-disable-next-line */
|
|
||||||
electron = require('electron')
|
|
||||||
shell = electron.shell
|
|
||||||
useElectron = true
|
useElectron = true
|
||||||
} else {
|
ipcRenderer = require('electron').ipcRenderer
|
||||||
useElectron = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -90,12 +84,12 @@ export default Vue.extend({
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
const v = this
|
const v = this
|
||||||
this.$store.dispatch('grabUserSettings').then(() => {
|
this.$store.dispatch('grabUserSettings').then(() => {
|
||||||
this.$store.dispatch('grabAllProfiles', this.$t('Profile.All Channels')).then(() => {
|
this.$store.dispatch('grabAllProfiles', this.$t('Profile.All Channels')).then(async () => {
|
||||||
this.$store.dispatch('grabHistory')
|
this.$store.dispatch('grabHistory')
|
||||||
this.$store.dispatch('grabAllPlaylists')
|
this.$store.dispatch('grabAllPlaylists')
|
||||||
this.$store.commit('setUsingElectron', useElectron)
|
this.$store.commit('setUsingElectron', useElectron)
|
||||||
this.checkThemeSettings()
|
this.checkThemeSettings()
|
||||||
this.checkLocale()
|
await this.checkLocale()
|
||||||
|
|
||||||
v.dataReady = true
|
v.dataReady = true
|
||||||
|
|
||||||
|
@ -115,14 +109,15 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
checkLocale: function () {
|
checkLocale: async function () {
|
||||||
const locale = localStorage.getItem('locale')
|
const locale = localStorage.getItem('locale')
|
||||||
|
|
||||||
if (locale === null || locale === 'system') {
|
if (locale === null || locale === 'system') {
|
||||||
const systemLocale = app.getLocale().replace(/-|_/, '_')
|
const systemLocale = await this.getLocale()
|
||||||
|
|
||||||
const findLocale = Object.keys(this.$i18n.messages).find((locale) => {
|
const findLocale = Object.keys(this.$i18n.messages).find((locale) => {
|
||||||
const localeName = locale.replace(/-|_/, '_')
|
const localeName = locale.replace('-', '_')
|
||||||
return localeName.includes(systemLocale)
|
return localeName.includes(systemLocale.replace('-', '_'))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (typeof findLocale !== 'undefined') {
|
if (typeof findLocale !== 'undefined') {
|
||||||
|
@ -248,7 +243,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
handleNewBlogBannerClick: function (response) {
|
handleNewBlogBannerClick: function (response) {
|
||||||
if (response) {
|
if (response) {
|
||||||
shell.openExternal(this.latestBlogUrl)
|
this.openExternalLink(this.latestBlogUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showBlogBanner = false
|
this.showBlogBanner = false
|
||||||
|
@ -256,7 +251,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
openDownloadsPage: function () {
|
openDownloadsPage: function () {
|
||||||
const url = 'https://freetubeapp.io#download'
|
const url = 'https://freetubeapp.io#download'
|
||||||
shell.openExternal(url)
|
this.openExternalLink(url)
|
||||||
this.showReleaseNotes = false
|
this.showReleaseNotes = false
|
||||||
this.showUpdatesBanner = false
|
this.showUpdatesBanner = false
|
||||||
},
|
},
|
||||||
|
@ -301,9 +296,7 @@ export default Vue.extend({
|
||||||
this.handleYoutubeLink(el.href)
|
this.handleYoutubeLink(el.href)
|
||||||
} else {
|
} else {
|
||||||
// Open links externally by default
|
// Open links externally by default
|
||||||
if (typeof (shell) !== 'undefined') {
|
this.openExternalLink(el.href)
|
||||||
shell.openExternal(el.href)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -385,23 +378,24 @@ export default Vue.extend({
|
||||||
|
|
||||||
enableOpenUrl: function () {
|
enableOpenUrl: function () {
|
||||||
const v = this
|
const v = this
|
||||||
electron.ipcRenderer.on('openUrl', function (event, url) {
|
ipcRenderer.on('openUrl', function (event, url) {
|
||||||
if (url) {
|
if (url) {
|
||||||
v.handleYoutubeLink(url)
|
v.handleYoutubeLink(url)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.ipcRenderer.send('appReady')
|
ipcRenderer.send('appReady')
|
||||||
},
|
},
|
||||||
|
|
||||||
setBoundsOnClose: function () {
|
setBoundsOnClose: function () {
|
||||||
window.onbeforeunload = (e) => {
|
window.onbeforeunload = (e) => {
|
||||||
electron.ipcRenderer.send('setBounds')
|
ipcRenderer.send('setBounds')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
...mapActions([
|
...mapActions([
|
||||||
'showToast'
|
'showToast',
|
||||||
|
'openExternalLink'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,9 +10,7 @@ import fs from 'fs'
|
||||||
import { opmlToJSON } from 'opml-to-json'
|
import { opmlToJSON } from 'opml-to-json'
|
||||||
import ytch from 'yt-channel-info'
|
import ytch from 'yt-channel-info'
|
||||||
|
|
||||||
const remote = require('@electron/remote')
|
// FIXME: Missing web logic branching
|
||||||
const app = remote.app
|
|
||||||
const dialog = remote.dialog
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'DataSettings',
|
name: 'DataSettings',
|
||||||
|
@ -210,7 +208,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
importFreeTubeSubscriptions: function () {
|
importFreeTubeSubscriptions: async function () {
|
||||||
const options = {
|
const options = {
|
||||||
properties: ['openFile'],
|
properties: ['openFile'],
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -221,14 +219,13 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showOpenDialog(options).then((response) => {
|
const response = await this.showOpenDialog(options)
|
||||||
if (response.canceled || response.filePaths.length === 0) {
|
if (response.canceled || response.filePaths.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePaths[0]
|
const filePath = response.filePaths[0]
|
||||||
this.handleFreetubeImportFile(filePath)
|
this.handleFreetubeImportFile(filePath)
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleYoutubeImportFile: function (filePath) {
|
handleYoutubeImportFile: function (filePath) {
|
||||||
|
@ -313,7 +310,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
importYouTubeSubscriptions: function () {
|
importYouTubeSubscriptions: async function () {
|
||||||
const options = {
|
const options = {
|
||||||
properties: ['openFile'],
|
properties: ['openFile'],
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -324,17 +321,16 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showOpenDialog(options).then(async (response) => {
|
const response = await this.showOpenDialog(options)
|
||||||
if (response.canceled || response.filePaths.length === 0) {
|
if (response.canceled || response.filePaths.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePaths[0]
|
const filePath = response.filePaths[0]
|
||||||
this.handleYoutubeImportFile(filePath)
|
this.handleYoutubeImportFile(filePath)
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
importOpmlYouTubeSubscriptions: function () {
|
importOpmlYouTubeSubscriptions: async function () {
|
||||||
const options = {
|
const options = {
|
||||||
properties: ['openFile'],
|
properties: ['openFile'],
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -345,148 +341,38 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showOpenDialog(options).then(async (response) => {
|
const response = await this.showOpenDialog(options)
|
||||||
if (response.canceled || response.filePaths.length === 0) {
|
if (response.canceled || response.filePaths.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
const filePath = response.filePaths[0]
|
|
||||||
|
|
||||||
fs.readFile(filePath, async (err, data) => {
|
|
||||||
if (err) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to read file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${err}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
opmlToJSON(data).then((json) => {
|
|
||||||
let feedData = json.children[0].children
|
|
||||||
|
|
||||||
if (typeof feedData === 'undefined') {
|
|
||||||
if (json.title.includes('gPodder')) {
|
|
||||||
feedData = json.children
|
|
||||||
} else {
|
|
||||||
const message = this.$t('Settings.Data Settings.Invalid subscriptions file')
|
|
||||||
this.showToast({
|
|
||||||
message: message
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const primaryProfile = JSON.parse(JSON.stringify(this.profileList[0]))
|
|
||||||
const subscriptions = []
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.This might take a while, please wait')
|
|
||||||
})
|
|
||||||
|
|
||||||
this.updateShowProgressBar(true)
|
|
||||||
this.setProgressBarPercentage(0)
|
|
||||||
|
|
||||||
let count = 0
|
|
||||||
|
|
||||||
feedData.forEach(async (channel, index) => {
|
|
||||||
const channelId = channel.xmlurl.replace('https://www.youtube.com/feeds/videos.xml?channel_id=', '')
|
|
||||||
let channelInfo
|
|
||||||
if (this.backendPreference === 'invidious') {
|
|
||||||
channelInfo = await this.getChannelInfoInvidious(channelId)
|
|
||||||
} else {
|
|
||||||
channelInfo = await this.getChannelInfoLocal(channelId)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof channelInfo.author !== 'undefined') {
|
|
||||||
const subscription = {
|
|
||||||
id: channelId,
|
|
||||||
name: channelInfo.author,
|
|
||||||
thumbnail: channelInfo.authorThumbnails[1].url
|
|
||||||
}
|
|
||||||
|
|
||||||
const subExists = primaryProfile.subscriptions.findIndex((sub) => {
|
|
||||||
return sub.id === subscription.id || sub.name === subscription.name
|
|
||||||
})
|
|
||||||
|
|
||||||
if (subExists === -1) {
|
|
||||||
subscriptions.push(subscription)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
count++
|
|
||||||
|
|
||||||
const progressPercentage = (count / feedData.length) * 100
|
|
||||||
this.setProgressBarPercentage(progressPercentage)
|
|
||||||
|
|
||||||
if (count === feedData.length) {
|
|
||||||
primaryProfile.subscriptions = primaryProfile.subscriptions.concat(subscriptions)
|
|
||||||
this.updateProfile(primaryProfile)
|
|
||||||
|
|
||||||
if (subscriptions.length < count) {
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.One or more subscriptions were unable to be imported')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.All subscriptions have been successfully imported')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateShowProgressBar(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}).catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
console.log('error reading')
|
|
||||||
const message = this.$t('Settings.Data Settings.Invalid subscriptions file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${err}`
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
importNewPipeSubscriptions: function () {
|
|
||||||
const options = {
|
|
||||||
properties: ['openFile'],
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
name: 'Database File',
|
|
||||||
extensions: ['json']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showOpenDialog(options).then(async (response) => {
|
const filePath = response.filePaths[0]
|
||||||
if (response.canceled || response.filePaths.length === 0) {
|
|
||||||
|
fs.readFile(filePath, async (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to read file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${err}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePaths[0]
|
opmlToJSON(data).then((json) => {
|
||||||
|
let feedData = json.children[0].children
|
||||||
|
|
||||||
fs.readFile(filePath, async (err, data) => {
|
if (typeof feedData === 'undefined') {
|
||||||
if (err) {
|
if (json.title.includes('gPodder')) {
|
||||||
const message = this.$t('Settings.Data Settings.Unable to read file')
|
feedData = json.children
|
||||||
this.showToast({
|
} else {
|
||||||
message: `${message}: ${err}`
|
const message = this.$t('Settings.Data Settings.Invalid subscriptions file')
|
||||||
})
|
this.showToast({
|
||||||
return
|
message: message
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newPipeData = JSON.parse(data)
|
|
||||||
|
|
||||||
if (typeof newPipeData.subscriptions === 'undefined') {
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.Invalid subscriptions file')
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const newPipeSubscriptions = newPipeData.subscriptions
|
|
||||||
|
|
||||||
const primaryProfile = JSON.parse(JSON.stringify(this.profileList[0]))
|
const primaryProfile = JSON.parse(JSON.stringify(this.profileList[0]))
|
||||||
const subscriptions = []
|
const subscriptions = []
|
||||||
|
|
||||||
|
@ -499,8 +385,8 @@ export default Vue.extend({
|
||||||
|
|
||||||
let count = 0
|
let count = 0
|
||||||
|
|
||||||
newPipeSubscriptions.forEach(async (channel, index) => {
|
feedData.forEach(async (channel, index) => {
|
||||||
const channelId = channel.url.replace(/https:\/\/(www\.)?youtube\.com\/channel\//, '')
|
const channelId = channel.xmlurl.replace('https://www.youtube.com/feeds/videos.xml?channel_id=', '')
|
||||||
let channelInfo
|
let channelInfo
|
||||||
if (this.backendPreference === 'invidious') {
|
if (this.backendPreference === 'invidious') {
|
||||||
channelInfo = await this.getChannelInfoInvidious(channelId)
|
channelInfo = await this.getChannelInfoInvidious(channelId)
|
||||||
|
@ -526,10 +412,10 @@ export default Vue.extend({
|
||||||
|
|
||||||
count++
|
count++
|
||||||
|
|
||||||
const progressPercentage = (count / newPipeSubscriptions.length) * 100
|
const progressPercentage = (count / feedData.length) * 100
|
||||||
this.setProgressBarPercentage(progressPercentage)
|
this.setProgressBarPercentage(progressPercentage)
|
||||||
|
|
||||||
if (count === newPipeSubscriptions.length) {
|
if (count === feedData.length) {
|
||||||
primaryProfile.subscriptions = primaryProfile.subscriptions.concat(subscriptions)
|
primaryProfile.subscriptions = primaryProfile.subscriptions.concat(subscriptions)
|
||||||
this.updateProfile(primaryProfile)
|
this.updateProfile(primaryProfile)
|
||||||
|
|
||||||
|
@ -546,6 +432,114 @@ export default Vue.extend({
|
||||||
this.updateShowProgressBar(false)
|
this.updateShowProgressBar(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
console.log('error reading')
|
||||||
|
const message = this.$t('Settings.Data Settings.Invalid subscriptions file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${err}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
importNewPipeSubscriptions: async function () {
|
||||||
|
const options = {
|
||||||
|
properties: ['openFile'],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'Database File',
|
||||||
|
extensions: ['json']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await this.showOpenDialog(options)
|
||||||
|
if (response.canceled || response.filePaths.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePaths[0]
|
||||||
|
|
||||||
|
fs.readFile(filePath, async (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to read file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${err}`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPipeData = JSON.parse(data)
|
||||||
|
|
||||||
|
if (typeof newPipeData.subscriptions === 'undefined') {
|
||||||
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.Invalid subscriptions file')
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPipeSubscriptions = newPipeData.subscriptions
|
||||||
|
|
||||||
|
const primaryProfile = JSON.parse(JSON.stringify(this.profileList[0]))
|
||||||
|
const subscriptions = []
|
||||||
|
|
||||||
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.This might take a while, please wait')
|
||||||
|
})
|
||||||
|
|
||||||
|
this.updateShowProgressBar(true)
|
||||||
|
this.setProgressBarPercentage(0)
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
|
||||||
|
newPipeSubscriptions.forEach(async (channel, index) => {
|
||||||
|
const channelId = channel.url.replace(/https:\/\/(www\.)?youtube\.com\/channel\//, '')
|
||||||
|
let channelInfo
|
||||||
|
if (this.backendPreference === 'invidious') {
|
||||||
|
channelInfo = await this.getChannelInfoInvidious(channelId)
|
||||||
|
} else {
|
||||||
|
channelInfo = await this.getChannelInfoLocal(channelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof channelInfo.author !== 'undefined') {
|
||||||
|
const subscription = {
|
||||||
|
id: channelId,
|
||||||
|
name: channelInfo.author,
|
||||||
|
thumbnail: channelInfo.authorThumbnails[1].url
|
||||||
|
}
|
||||||
|
|
||||||
|
const subExists = primaryProfile.subscriptions.findIndex((sub) => {
|
||||||
|
return sub.id === subscription.id || sub.name === subscription.name
|
||||||
|
})
|
||||||
|
|
||||||
|
if (subExists === -1) {
|
||||||
|
subscriptions.push(subscription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count++
|
||||||
|
|
||||||
|
const progressPercentage = (count / newPipeSubscriptions.length) * 100
|
||||||
|
this.setProgressBarPercentage(progressPercentage)
|
||||||
|
|
||||||
|
if (count === newPipeSubscriptions.length) {
|
||||||
|
primaryProfile.subscriptions = primaryProfile.subscriptions.concat(subscriptions)
|
||||||
|
this.updateProfile(primaryProfile)
|
||||||
|
|
||||||
|
if (subscriptions.length < count) {
|
||||||
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.One or more subscriptions were unable to be imported')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.All subscriptions have been successfully imported')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateShowProgressBar(false)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -575,7 +569,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
exportFreeTubeSubscriptions: async function () {
|
exportFreeTubeSubscriptions: async function () {
|
||||||
await this.compactProfiles()
|
await this.compactProfiles()
|
||||||
const userData = app.getPath('userData')
|
const userData = await this.getUserDataPath()
|
||||||
const subscriptionsDb = `${userData}/profiles.db`
|
const subscriptionsDb = `${userData}/profiles.db`
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
let dateMonth = date.getMonth() + 1
|
let dateMonth = date.getMonth() + 1
|
||||||
|
@ -603,41 +597,40 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showSaveDialog(options).then((response) => {
|
const response = await this.showSaveDialog(options)
|
||||||
if (response.canceled || response.filePath === '') {
|
if (response.canceled || response.filePath === '') {
|
||||||
// User canceled the save dialog
|
// User canceled the save dialog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePath
|
||||||
|
|
||||||
|
fs.readFile(subscriptionsDb, (readErr, data) => {
|
||||||
|
if (readErr) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to read file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${readErr}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePath
|
fs.writeFile(filePath, data, (writeErr) => {
|
||||||
|
if (writeErr) {
|
||||||
fs.readFile(subscriptionsDb, (readErr, data) => {
|
const message = this.$t('Settings.Data Settings.Unable to write file')
|
||||||
if (readErr) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to read file')
|
|
||||||
this.showToast({
|
this.showToast({
|
||||||
message: `${message}: ${readErr}`
|
message: `${message}: ${writeErr}`
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFile(filePath, data, (writeErr) => {
|
this.showToast({
|
||||||
if (writeErr) {
|
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
||||||
const message = this.$t('Settings.Data Settings.Unable to write file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${writeErr}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
exportYouTubeSubscriptions: function () {
|
exportYouTubeSubscriptions: async function () {
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
let dateMonth = date.getMonth() + 1
|
let dateMonth = date.getMonth() + 1
|
||||||
|
|
||||||
|
@ -700,26 +693,25 @@ export default Vue.extend({
|
||||||
return object
|
return object
|
||||||
})
|
})
|
||||||
|
|
||||||
dialog.showSaveDialog(options).then((response) => {
|
const response = await this.showSaveDialog(options)
|
||||||
if (response.canceled || response.filePath === '') {
|
if (response.canceled || response.filePath === '') {
|
||||||
// User canceled the save dialog
|
// User canceled the save dialog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePath
|
||||||
|
|
||||||
|
fs.writeFile(filePath, JSON.stringify(subscriptionsObject), (writeErr) => {
|
||||||
|
if (writeErr) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to write file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${writeErr}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePath
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
||||||
fs.writeFile(filePath, JSON.stringify(subscriptionsObject), (writeErr) => {
|
|
||||||
if (writeErr) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to write file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${writeErr}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -766,31 +758,30 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
dialog.showSaveDialog(options).then((response) => {
|
const response = await this.showSaveDialog(options)
|
||||||
if (response.canceled || response.filePath === '') {
|
if (response.canceled || response.filePath === '') {
|
||||||
// User canceled the save dialog
|
// User canceled the save dialog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePath
|
||||||
|
|
||||||
|
fs.writeFile(filePath, opmlData, (writeErr) => {
|
||||||
|
if (writeErr) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to write file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${writeErr}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePath
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
||||||
fs.writeFile(filePath, opmlData, (writeErr) => {
|
|
||||||
if (writeErr) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to write file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${writeErr}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
exportNewPipeSubscriptions: function () {
|
exportNewPipeSubscriptions: async function () {
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
let dateMonth = date.getMonth() + 1
|
let dateMonth = date.getMonth() + 1
|
||||||
|
|
||||||
|
@ -834,32 +825,31 @@ export default Vue.extend({
|
||||||
newPipeObject.subscriptions.push(subscription)
|
newPipeObject.subscriptions.push(subscription)
|
||||||
})
|
})
|
||||||
|
|
||||||
dialog.showSaveDialog(options).then((response) => {
|
const response = await this.showSaveDialog(options)
|
||||||
if (response.canceled || response.filePath === '') {
|
if (response.canceled || response.filePath === '') {
|
||||||
// User canceled the save dialog
|
// User canceled the save dialog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePath
|
||||||
|
|
||||||
|
fs.writeFile(filePath, JSON.stringify(newPipeObject), (writeErr) => {
|
||||||
|
if (writeErr) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to write file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${writeErr}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePath
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
||||||
fs.writeFile(filePath, JSON.stringify(newPipeObject), (writeErr) => {
|
|
||||||
if (writeErr) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to write file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${writeErr}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.Subscriptions have been successfully exported')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
checkForLegacySubscriptions: function () {
|
checkForLegacySubscriptions: async function () {
|
||||||
let dbLocation = app.getPath('userData')
|
let dbLocation = await this.getUserDataPath()
|
||||||
dbLocation = dbLocation + '/subscriptions.db'
|
dbLocation = dbLocation + '/subscriptions.db'
|
||||||
this.handleFreetubeImportFile(dbLocation)
|
this.handleFreetubeImportFile(dbLocation)
|
||||||
fs.unlink(dbLocation, (err) => {
|
fs.unlink(dbLocation, (err) => {
|
||||||
|
@ -869,7 +859,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
importHistory: function () {
|
importHistory: async function () {
|
||||||
const options = {
|
const options = {
|
||||||
properties: ['openFile'],
|
properties: ['openFile'],
|
||||||
filters: [
|
filters: [
|
||||||
|
@ -880,79 +870,78 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showOpenDialog(options).then((response) => {
|
const response = await this.showOpenDialog(options)
|
||||||
if (response.canceled || response.filePaths.length === 0) {
|
if (response.canceled || response.filePaths.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePaths[0]
|
||||||
|
|
||||||
|
fs.readFile(filePath, async (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to read file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${err}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePaths[0]
|
let textDecode = new TextDecoder('utf-8').decode(data)
|
||||||
|
textDecode = textDecode.split('\n')
|
||||||
|
textDecode.pop()
|
||||||
|
|
||||||
fs.readFile(filePath, async (err, data) => {
|
textDecode.forEach((history) => {
|
||||||
if (err) {
|
const historyData = JSON.parse(history)
|
||||||
const message = this.$t('Settings.Data Settings.Unable to read file')
|
// We would technically already be done by the time the data is parsed,
|
||||||
this.showToast({
|
// however we want to limit the possibility of malicious data being sent
|
||||||
message: `${message}: ${err}`
|
// to the app, so we'll only grab the data we need here.
|
||||||
})
|
const requiredKeys = [
|
||||||
return
|
'_id',
|
||||||
}
|
'author',
|
||||||
|
'authorId',
|
||||||
|
'description',
|
||||||
|
'isLive',
|
||||||
|
'lengthSeconds',
|
||||||
|
'paid',
|
||||||
|
'published',
|
||||||
|
'timeWatched',
|
||||||
|
'title',
|
||||||
|
'type',
|
||||||
|
'videoId',
|
||||||
|
'viewCount',
|
||||||
|
'watchProgress'
|
||||||
|
]
|
||||||
|
|
||||||
let textDecode = new TextDecoder('utf-8').decode(data)
|
const historyObject = {}
|
||||||
textDecode = textDecode.split('\n')
|
|
||||||
textDecode.pop()
|
|
||||||
|
|
||||||
textDecode.forEach((history) => {
|
Object.keys(historyData).forEach((key) => {
|
||||||
const historyData = JSON.parse(history)
|
if (!requiredKeys.includes(key)) {
|
||||||
// We would technically already be done by the time the data is parsed,
|
|
||||||
// however we want to limit the possibility of malicious data being sent
|
|
||||||
// to the app, so we'll only grab the data we need here.
|
|
||||||
const requiredKeys = [
|
|
||||||
'_id',
|
|
||||||
'author',
|
|
||||||
'authorId',
|
|
||||||
'description',
|
|
||||||
'isLive',
|
|
||||||
'lengthSeconds',
|
|
||||||
'paid',
|
|
||||||
'published',
|
|
||||||
'timeWatched',
|
|
||||||
'title',
|
|
||||||
'type',
|
|
||||||
'videoId',
|
|
||||||
'viewCount',
|
|
||||||
'watchProgress'
|
|
||||||
]
|
|
||||||
|
|
||||||
const historyObject = {}
|
|
||||||
|
|
||||||
Object.keys(historyData).forEach((key) => {
|
|
||||||
if (!requiredKeys.includes(key)) {
|
|
||||||
this.showToast({
|
|
||||||
message: `Unknown data key: ${key}`
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
historyObject[key] = historyData[key]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Object.keys(historyObject).length < (requiredKeys.length - 2)) {
|
|
||||||
this.showToast({
|
this.showToast({
|
||||||
message: this.$t('Settings.Data Settings.History object has insufficient data, skipping item')
|
message: `Unknown data key: ${key}`
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.updateHistory(historyObject)
|
historyObject[key] = historyData[key]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.showToast({
|
if (Object.keys(historyObject).length < (requiredKeys.length - 2)) {
|
||||||
message: this.$t('Settings.Data Settings.All watched history has been successfully imported')
|
this.showToast({
|
||||||
})
|
message: this.$t('Settings.Data Settings.History object has insufficient data, skipping item')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.updateHistory(historyObject)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.showToast({
|
||||||
|
message: this.$t('Settings.Data Settings.All watched history has been successfully imported')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
exportHistory: async function () {
|
exportHistory: async function () {
|
||||||
await this.compactHistory()
|
await this.compactHistory()
|
||||||
const userData = app.getPath('userData')
|
const userData = await this.getUserDataPath()
|
||||||
const historyDb = `${userData}/history.db`
|
const historyDb = `${userData}/history.db`
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
let dateMonth = date.getMonth() + 1
|
let dateMonth = date.getMonth() + 1
|
||||||
|
@ -980,35 +969,34 @@ export default Vue.extend({
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showSaveDialog(options).then((response) => {
|
const response = await this.showSaveDialog(options)
|
||||||
if (response.canceled || response.filePath === '') {
|
if (response.canceled || response.filePath === '') {
|
||||||
// User canceled the save dialog
|
// User canceled the save dialog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = response.filePath
|
||||||
|
|
||||||
|
fs.readFile(historyDb, (readErr, data) => {
|
||||||
|
if (readErr) {
|
||||||
|
const message = this.$t('Settings.Data Settings.Unable to read file')
|
||||||
|
this.showToast({
|
||||||
|
message: `${message}: ${readErr}`
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = response.filePath
|
fs.writeFile(filePath, data, (writeErr) => {
|
||||||
|
if (writeErr) {
|
||||||
fs.readFile(historyDb, (readErr, data) => {
|
const message = this.$t('Settings.Data Settings.Unable to write file')
|
||||||
if (readErr) {
|
|
||||||
const message = this.$t('Settings.Data Settings.Unable to read file')
|
|
||||||
this.showToast({
|
this.showToast({
|
||||||
message: `${message}: ${readErr}`
|
message: `${message}: ${writeErr}`
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFile(filePath, data, (writeErr) => {
|
this.showToast({
|
||||||
if (writeErr) {
|
message: this.$t('Settings.Data Settings.All watched history has been successfully exported')
|
||||||
const message = this.$t('Settings.Data Settings.Unable to write file')
|
|
||||||
this.showToast({
|
|
||||||
message: `${message}: ${writeErr}`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showToast({
|
|
||||||
message: this.$t('Settings.Data Settings.All watched history has been successfully exported')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1114,7 +1102,10 @@ export default Vue.extend({
|
||||||
'compactHistory',
|
'compactHistory',
|
||||||
'showToast',
|
'showToast',
|
||||||
'getRandomColor',
|
'getRandomColor',
|
||||||
'calculateColorLuminance'
|
'calculateColorLuminance',
|
||||||
|
'showOpenDialog',
|
||||||
|
'showSaveDialog',
|
||||||
|
'getUserDataPath'
|
||||||
]),
|
]),
|
||||||
|
|
||||||
...mapMutations([
|
...mapMutations([
|
||||||
|
|
|
@ -60,10 +60,6 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
usingElectron: function () {
|
|
||||||
return this.$store.getters.getUsingElectron
|
|
||||||
},
|
|
||||||
|
|
||||||
historyCache: function () {
|
historyCache: function () {
|
||||||
return this.$store.getters.getHistoryCache
|
return this.$store.getters.getHistoryCache
|
||||||
},
|
},
|
||||||
|
@ -216,10 +212,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'openYoutube':
|
case 'openYoutube':
|
||||||
if (this.usingElectron) {
|
this.openExternalLink(this.youtubeUrl)
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(this.youtubeUrl)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case 'copyYoutubeEmbed':
|
case 'copyYoutubeEmbed':
|
||||||
navigator.clipboard.writeText(this.youtubeEmbedUrl)
|
navigator.clipboard.writeText(this.youtubeEmbedUrl)
|
||||||
|
@ -228,10 +221,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'openYoutubeEmbed':
|
case 'openYoutubeEmbed':
|
||||||
if (this.usingElectron) {
|
this.openExternalLink(this.youtubeEmbedUrl)
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(this.youtubeEmbedUrl)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case 'copyInvidious':
|
case 'copyInvidious':
|
||||||
navigator.clipboard.writeText(this.invidiousUrl)
|
navigator.clipboard.writeText(this.invidiousUrl)
|
||||||
|
@ -240,11 +230,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'openInvidious':
|
case 'openInvidious':
|
||||||
if (this.usingElectron) {
|
this.openExternalLink(this.invidiousUrl)
|
||||||
console.log('using electron')
|
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(this.invidiousUrl)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case 'copyYoutubeChannel':
|
case 'copyYoutubeChannel':
|
||||||
navigator.clipboard.writeText(this.youtubeChannelUrl)
|
navigator.clipboard.writeText(this.youtubeChannelUrl)
|
||||||
|
@ -253,10 +239,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'openYoutubeChannel':
|
case 'openYoutubeChannel':
|
||||||
if (this.usingElectron) {
|
this.openExternalLink(this.youtubeChannelUrl)
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(this.youtubeChannelUrl)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
case 'copyInvidiousChannel':
|
case 'copyInvidiousChannel':
|
||||||
navigator.clipboard.writeText(this.invidiousChannelUrl)
|
navigator.clipboard.writeText(this.invidiousChannelUrl)
|
||||||
|
@ -265,10 +248,7 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'openInvidiousChannel':
|
case 'openInvidiousChannel':
|
||||||
if (this.usingElectron) {
|
this.openExternalLink(this.invidiousChannelUrl)
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(this.invidiousChannelUrl)
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -460,7 +440,8 @@ export default Vue.extend({
|
||||||
'updateHistory',
|
'updateHistory',
|
||||||
'removeFromHistory',
|
'removeFromHistory',
|
||||||
'addVideo',
|
'addVideo',
|
||||||
'removeVideo'
|
'removeVideo',
|
||||||
|
'openExternalLink'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -34,10 +34,6 @@ export default Vue.extend({
|
||||||
return this.$store.getters.getInvidiousInstance
|
return this.$store.getters.getInvidiousInstance
|
||||||
},
|
},
|
||||||
|
|
||||||
usingElectron: function () {
|
|
||||||
return this.$store.getters.getUsingElectron
|
|
||||||
},
|
|
||||||
|
|
||||||
invidiousURL() {
|
invidiousURL() {
|
||||||
return `${this.invidiousInstance}/watch?v=${this.id}`
|
return `${this.invidiousInstance}/watch?v=${this.id}`
|
||||||
},
|
},
|
||||||
|
@ -63,15 +59,8 @@ export default Vue.extend({
|
||||||
navigator.clipboard.writeText(text)
|
navigator.clipboard.writeText(text)
|
||||||
},
|
},
|
||||||
|
|
||||||
open(url) {
|
|
||||||
if (this.usingElectron) {
|
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(url)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
openInvidious() {
|
openInvidious() {
|
||||||
this.open(this.getFinalUrl(this.invidiousURL))
|
this.openExternalLink(this.getFinalUrl(this.invidiousURL))
|
||||||
this.$refs.iconButton.focusOut()
|
this.$refs.iconButton.focusOut()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -84,7 +73,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
openYoutube() {
|
openYoutube() {
|
||||||
this.open(this.getFinalUrl(this.youtubeURL))
|
this.openExternalLink(this.getFinalUrl(this.youtubeURL))
|
||||||
this.$refs.iconButton.focusOut()
|
this.$refs.iconButton.focusOut()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -97,7 +86,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
openYoutubeEmbed() {
|
openYoutubeEmbed() {
|
||||||
this.open(this.getFinalUrl(this.youtubeEmbedURL))
|
this.openExternalLink(this.getFinalUrl(this.youtubeEmbedURL))
|
||||||
this.$refs.iconButton.focusOut()
|
this.$refs.iconButton.focusOut()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -110,7 +99,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
openInvidiousEmbed() {
|
openInvidiousEmbed() {
|
||||||
this.open(this.getFinalUrl(this.invidiousEmbedURL))
|
this.openExternalLink(this.getFinalUrl(this.invidiousEmbedURL))
|
||||||
this.$refs.iconButton.focusOut()
|
this.$refs.iconButton.focusOut()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -134,7 +123,8 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
...mapActions([
|
...mapActions([
|
||||||
'showToast'
|
'showToast',
|
||||||
|
'openExternalLink'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,8 +30,8 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||||
const { powerSaveBlocker } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
ipcRenderer.send('stopPowerSaveBlocker', this.powerSaveBlocker)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -189,8 +189,8 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||||
const { powerSaveBlocker } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
ipcRenderer.send('stopPowerSaveBlocker', this.powerSaveBlocker)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -274,18 +274,18 @@ export default Vue.extend({
|
||||||
v.$emit('error', error.target.player.error_)
|
v.$emit('error', error.target.player.error_)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.player.on('play', function () {
|
this.player.on('play', async function () {
|
||||||
if (this.usingElectron) {
|
if (this.usingElectron) {
|
||||||
const { powerSaveBlocker } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
|
this.powerSaveBlocker =
|
||||||
this.powerSaveBlocker = powerSaveBlocker.start('prevent-display-sleep')
|
await ipcRenderer.invoke('startPowerSaveBlocker', 'prevent-display-sleep')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.player.on('pause', function () {
|
this.player.on('pause', function () {
|
||||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||||
const { powerSaveBlocker } = require('electron')
|
const { ipcRenderer } = require('electron')
|
||||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
ipcRenderer.send('stopPowerSaveBlocker', this.powerSaveBlocker)
|
||||||
this.powerSaveBlocker = null
|
this.powerSaveBlocker = null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import { mapActions } from 'vuex'
|
import { mapActions } from 'vuex'
|
||||||
import { app } from '@electron/remote'
|
|
||||||
import FtCard from '../ft-card/ft-card.vue'
|
import FtCard from '../ft-card/ft-card.vue'
|
||||||
import FtSelect from '../ft-select/ft-select.vue'
|
import FtSelect from '../ft-select/ft-select.vue'
|
||||||
import FtInput from '../ft-input/ft-input.vue'
|
import FtInput from '../ft-input/ft-input.vue'
|
||||||
|
@ -59,6 +58,11 @@ export default Vue.extend({
|
||||||
isDev: function () {
|
isDev: function () {
|
||||||
return process.env.NODE_ENV === 'development'
|
return process.env.NODE_ENV === 'development'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
usingElectron: function () {
|
||||||
|
return this.$store.getters.getUsingElectron
|
||||||
|
},
|
||||||
|
|
||||||
invidiousInstance: function () {
|
invidiousInstance: function () {
|
||||||
return this.$store.getters.getInvidiousInstance
|
return this.$store.getters.getInvidiousInstance
|
||||||
},
|
},
|
||||||
|
@ -192,12 +196,13 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateLocale: function (locale) {
|
updateLocale: async function (locale) {
|
||||||
if (locale === 'system') {
|
if (locale === 'system') {
|
||||||
const systemLocale = app.getLocale().replace(/-|_/, '_')
|
const systemLocale = await this.getLocale()
|
||||||
|
|
||||||
const findLocale = Object.keys(this.$i18n.messages).find((locale) => {
|
const findLocale = Object.keys(this.$i18n.messages).find((locale) => {
|
||||||
const localeName = locale.replace(/-|_/, '_')
|
const localeName = locale.replace('-', '_')
|
||||||
return localeName.includes(systemLocale)
|
return localeName.includes(systemLocale.replace('-', '_'))
|
||||||
})
|
})
|
||||||
|
|
||||||
if (typeof findLocale !== 'undefined') {
|
if (typeof findLocale !== 'undefined') {
|
||||||
|
@ -240,7 +245,8 @@ export default Vue.extend({
|
||||||
'updateThumbnailPreference',
|
'updateThumbnailPreference',
|
||||||
'updateInvidiousInstance',
|
'updateInvidiousInstance',
|
||||||
'updateForceLocalBackendForLegacy',
|
'updateForceLocalBackendForLegacy',
|
||||||
'getRegionData'
|
'getRegionData',
|
||||||
|
'getLocale'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
import FtListDropdown from '../ft-list-dropdown/ft-list-dropdown.vue'
|
import FtListDropdown from '../ft-list-dropdown/ft-list-dropdown.vue'
|
||||||
import { shell } from 'electron'
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'FtElementList',
|
name: 'FtElementList',
|
||||||
|
@ -101,15 +101,19 @@ export default Vue.extend({
|
||||||
navigator.clipboard.writeText(youtubeUrl)
|
navigator.clipboard.writeText(youtubeUrl)
|
||||||
break
|
break
|
||||||
case 'openYoutube':
|
case 'openYoutube':
|
||||||
shell.openExternal(youtubeUrl)
|
this.openExternalLink(youtubeUrl)
|
||||||
break
|
break
|
||||||
case 'copyInvidious':
|
case 'copyInvidious':
|
||||||
navigator.clipboard.writeText(invidiousUrl)
|
navigator.clipboard.writeText(invidiousUrl)
|
||||||
break
|
break
|
||||||
case 'openInvidious':
|
case 'openInvidious':
|
||||||
shell.openExternal(invidiousUrl)
|
this.openExternalLink(invidiousUrl)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
...mapActions([
|
||||||
|
'openExternalLink'
|
||||||
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,9 @@ import FtInput from '../ft-input/ft-input.vue'
|
||||||
import FtLoader from '../ft-loader/ft-loader.vue'
|
import FtLoader from '../ft-loader/ft-loader.vue'
|
||||||
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||||
|
|
||||||
import electron from 'electron'
|
// FIXME: Missing web logic branching
|
||||||
|
|
||||||
|
import { ipcRenderer } from 'electron'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -109,11 +111,11 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
enableProxy: function () {
|
enableProxy: function () {
|
||||||
electron.ipcRenderer.send('enableProxy', this.proxyUrl)
|
ipcRenderer.send('enableProxy', this.proxyUrl)
|
||||||
},
|
},
|
||||||
|
|
||||||
disableProxy: function () {
|
disableProxy: function () {
|
||||||
electron.ipcRenderer.send('disableProxy')
|
ipcRenderer.send('disableProxy')
|
||||||
},
|
},
|
||||||
|
|
||||||
testProxy: function () {
|
testProxy: function () {
|
||||||
|
|
|
@ -146,6 +146,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
handleUiScale: function (value) {
|
handleUiScale: function (value) {
|
||||||
|
// FIXME: No electron safeguard
|
||||||
const { webFrame } = require('electron')
|
const { webFrame } = require('electron')
|
||||||
const zoomFactor = value / 100
|
const zoomFactor = value / 100
|
||||||
webFrame.setZoomFactor(zoomFactor)
|
webFrame.setZoomFactor(zoomFactor)
|
||||||
|
@ -167,12 +168,13 @@ export default Vue.extend({
|
||||||
|
|
||||||
this.updateDisableSmoothScrolling(this.disableSmoothScrollingToggleValue)
|
this.updateDisableSmoothScrolling(this.disableSmoothScrollingToggleValue)
|
||||||
|
|
||||||
const electron = require('electron')
|
// FIXME: No electron safeguard
|
||||||
|
const { ipcRenderer } = require('electron')
|
||||||
|
|
||||||
if (this.disableSmoothScrollingToggleValue) {
|
if (this.disableSmoothScrollingToggleValue) {
|
||||||
electron.ipcRenderer.send('disableSmoothScrolling')
|
ipcRenderer.send('disableSmoothScrolling')
|
||||||
} else {
|
} else {
|
||||||
electron.ipcRenderer.send('enableSmoothScrolling')
|
ipcRenderer.send('enableSmoothScrolling')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import FtProfileSelector from '../ft-profile-selector/ft-profile-selector.vue'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
import ytSuggest from 'youtube-suggest'
|
import ytSuggest from 'youtube-suggest'
|
||||||
const { ipcRenderer } = require('electron')
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'TopNav',
|
name: 'TopNav',
|
||||||
|
@ -24,6 +23,10 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
usingElectron: function () {
|
||||||
|
return this.$store.getters.getUsingElectron
|
||||||
|
},
|
||||||
|
|
||||||
enableSearchSuggestions: function () {
|
enableSearchSuggestions: function () {
|
||||||
return this.$store.getters.getEnableSearchSuggestions
|
return this.$store.getters.getEnableSearchSuggestions
|
||||||
},
|
},
|
||||||
|
@ -255,7 +258,12 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
createNewWindow: function () {
|
createNewWindow: function () {
|
||||||
ipcRenderer.send('createNewWindow')
|
if (this.usingElectron) {
|
||||||
|
const { ipcRenderer } = require('electron')
|
||||||
|
ipcRenderer.send('createNewWindow')
|
||||||
|
} else {
|
||||||
|
// Web placeholder
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
...mapActions([
|
...mapActions([
|
||||||
|
|
|
@ -6,7 +6,6 @@ import FtListDropdown from '../ft-list-dropdown/ft-list-dropdown.vue'
|
||||||
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||||
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
|
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
|
||||||
import FtShareButton from '../ft-share-button/ft-share-button.vue'
|
import FtShareButton from '../ft-share-button/ft-share-button.vue'
|
||||||
// import { shell } from 'electron'
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'WatchVideoInfo',
|
name: 'WatchVideoInfo',
|
||||||
|
@ -111,10 +110,6 @@ export default Vue.extend({
|
||||||
return this.$store.getters.getInvidiousInstance
|
return this.$store.getters.getInvidiousInstance
|
||||||
},
|
},
|
||||||
|
|
||||||
usingElectron: function () {
|
|
||||||
return this.$store.getters.getUsingElectron
|
|
||||||
},
|
|
||||||
|
|
||||||
profileList: function () {
|
profileList: function () {
|
||||||
return this.$store.getters.getProfileList
|
return this.$store.getters.getProfileList
|
||||||
},
|
},
|
||||||
|
@ -346,11 +341,6 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDownloadLink: function (url) {
|
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(url)
|
|
||||||
},
|
|
||||||
|
|
||||||
addToPlaylist: function () {
|
addToPlaylist: function () {
|
||||||
const videoData = {
|
const videoData = {
|
||||||
videoId: this.id,
|
videoId: this.id,
|
||||||
|
@ -396,7 +386,8 @@ export default Vue.extend({
|
||||||
'showToast',
|
'showToast',
|
||||||
'updateProfile',
|
'updateProfile',
|
||||||
'addVideo',
|
'addVideo',
|
||||||
'removeVideo'
|
'removeVideo',
|
||||||
|
'openExternalLink'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
icon="download"
|
icon="download"
|
||||||
:dropdown-names="downloadLinkNames"
|
:dropdown-names="downloadLinkNames"
|
||||||
:dropdown-values="downloadLinkValues"
|
:dropdown-values="downloadLinkValues"
|
||||||
@click="handleDownloadLink"
|
@click="openExternalLink"
|
||||||
/>
|
/>
|
||||||
<ft-icon-button
|
<ft-icon-button
|
||||||
v-if="!isUpcoming"
|
v-if="!isUpcoming"
|
||||||
|
|
|
@ -11,8 +11,8 @@ if (window && window.process && window.process.type === 'renderer') {
|
||||||
dbLocation = electron.remote.app.getPath('userData')
|
dbLocation = electron.remote.app.getPath('userData')
|
||||||
} */
|
} */
|
||||||
|
|
||||||
const remote = require('@electron/remote')
|
const { ipcRenderer } = require('electron')
|
||||||
dbLocation = remote.app.getPath('userData')
|
dbLocation = ipcRenderer.sendSync('getUserDataPathSync')
|
||||||
dbLocation = dbLocation + '/history.db'
|
dbLocation = dbLocation + '/history.db'
|
||||||
} else {
|
} else {
|
||||||
dbLocation = 'history.db'
|
dbLocation = 'history.db'
|
||||||
|
|
|
@ -13,9 +13,8 @@ if (window && window.process && window.process.type === 'renderer') {
|
||||||
//
|
//
|
||||||
// dbLocation += '/playlists.db'
|
// dbLocation += '/playlists.db'
|
||||||
|
|
||||||
const remote = require('@electron/remote')
|
const { ipcRenderer } = require('electron')
|
||||||
dbLocation = remote.app.getPath('userData')
|
dbLocation = ipcRenderer.sendSync('getUserDataPathSync')
|
||||||
|
|
||||||
dbLocation = dbLocation + '/playlists.db'
|
dbLocation = dbLocation + '/playlists.db'
|
||||||
} else {
|
} else {
|
||||||
dbLocation = 'playlists.db'
|
dbLocation = 'playlists.db'
|
||||||
|
|
|
@ -11,9 +11,8 @@ if (window && window.process && window.process.type === 'renderer') {
|
||||||
dbLocation = electron.remote.app.getPath('userData')
|
dbLocation = electron.remote.app.getPath('userData')
|
||||||
} */
|
} */
|
||||||
|
|
||||||
const remote = require('@electron/remote')
|
const { ipcRenderer } = require('electron')
|
||||||
dbLocation = remote.app.getPath('userData')
|
dbLocation = ipcRenderer.sendSync('getUserDataPathSync')
|
||||||
|
|
||||||
dbLocation = dbLocation + '/profiles.db'
|
dbLocation = dbLocation + '/profiles.db'
|
||||||
} else {
|
} else {
|
||||||
dbLocation = 'profiles.db'
|
dbLocation = 'profiles.db'
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Datastore from 'nedb'
|
import Datastore from 'nedb'
|
||||||
|
|
||||||
let dbLocation
|
let dbLocation
|
||||||
let electron = null
|
|
||||||
let webframe = null
|
let webframe = null
|
||||||
|
|
||||||
if (window && window.process && window.process.type === 'renderer') {
|
if (window && window.process && window.process.type === 'renderer') {
|
||||||
|
@ -13,12 +12,11 @@ if (window && window.process && window.process.type === 'renderer') {
|
||||||
dbLocation = electron.remote.app.getPath('userData')
|
dbLocation = electron.remote.app.getPath('userData')
|
||||||
} */
|
} */
|
||||||
|
|
||||||
electron = require('electron')
|
const electron = require('electron')
|
||||||
webframe = electron.webFrame
|
const ipcRenderer = electron.ipcRenderer
|
||||||
const remote = require('@electron/remote')
|
dbLocation = ipcRenderer.sendSync('getUserDataPathSync')
|
||||||
dbLocation = remote.app.getPath('userData')
|
|
||||||
|
|
||||||
dbLocation = dbLocation + '/settings.db'
|
dbLocation = dbLocation + '/settings.db'
|
||||||
|
webframe = electron.webframe
|
||||||
} else {
|
} else {
|
||||||
dbLocation = 'settings.db'
|
dbLocation = 'settings.db'
|
||||||
}
|
}
|
||||||
|
@ -332,7 +330,9 @@ const actions = {
|
||||||
commit('setBarColor', result.value)
|
commit('setBarColor', result.value)
|
||||||
break
|
break
|
||||||
case 'uiScale':
|
case 'uiScale':
|
||||||
webframe.setZoomFactor(parseInt(result.value) / 100)
|
if (webframe) {
|
||||||
|
webframe.setZoomFactor(parseInt(result.value) / 100)
|
||||||
|
}
|
||||||
commit('setUiScale', result.value)
|
commit('setUiScale', result.value)
|
||||||
break
|
break
|
||||||
case 'disableSmoothScrolling':
|
case 'disableSmoothScrolling':
|
||||||
|
|
|
@ -105,7 +105,67 @@ const getters = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper function that calls `ipcRenderer.invoke(IRCtype, payload)` if the user is
|
||||||
|
* using Electron or a provided custom callback otherwise.
|
||||||
|
* @param {Object} context Object
|
||||||
|
* @param {String} IRCtype String
|
||||||
|
* @param {Function} webCbk Function
|
||||||
|
* @param {Object} payload any (default: null)
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function invokeIRC(context, IRCtype, webCbk, payload = null) {
|
||||||
|
let response = null
|
||||||
|
const usingElectron = context.rootState.settings.usingElectron
|
||||||
|
if (usingElectron) {
|
||||||
|
const { ipcRenderer } = require('electron')
|
||||||
|
response = await ipcRenderer.invoke(IRCtype, payload)
|
||||||
|
} else if (webCbk) {
|
||||||
|
response = await webCbk()
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
openExternalLink ({ rootState }, url) {
|
||||||
|
const usingElectron = rootState.settings.usingElectron
|
||||||
|
if (usingElectron) {
|
||||||
|
const ipcRenderer = require('electron').ipcRenderer
|
||||||
|
ipcRenderer.send('openExternalLink', url)
|
||||||
|
} else {
|
||||||
|
// Web placeholder
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getLocale (context) {
|
||||||
|
const webCbk = () => {
|
||||||
|
if (navigator && navigator.language) {
|
||||||
|
return navigator.language
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await invokeIRC(context, 'getLocale', webCbk) || 'en-US'
|
||||||
|
},
|
||||||
|
|
||||||
|
async showOpenDialog (context, options) {
|
||||||
|
// TODO: implement showOpenDialog web compatible callback
|
||||||
|
const webCbk = () => null
|
||||||
|
return await invokeIRC(context, 'showOpenDialog', webCbk, options)
|
||||||
|
},
|
||||||
|
|
||||||
|
async showSaveDialog (context, options) {
|
||||||
|
// TODO: implement showSaveDialog web compatible callback
|
||||||
|
const webCbk = () => null
|
||||||
|
return await invokeIRC(context, 'showSaveDialog', webCbk, options)
|
||||||
|
},
|
||||||
|
|
||||||
|
async getUserDataPath (context) {
|
||||||
|
// TODO: implement getUserDataPath web compatible callback
|
||||||
|
const webCbk = () => null
|
||||||
|
return await invokeIRC(context, 'getUserDataPath', webCbk)
|
||||||
|
},
|
||||||
|
|
||||||
updateShowProgressBar ({ commit }, value) {
|
updateShowProgressBar ({ commit }, value) {
|
||||||
commit('setShowProgressBar', value)
|
commit('setShowProgressBar', value)
|
||||||
},
|
},
|
||||||
|
|
|
@ -88,18 +88,5 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
usingElectron: function () {
|
|
||||||
return this.$store.getters.getUsingElectron
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openUrl: function (url) {
|
|
||||||
if (this.usingElectron) {
|
|
||||||
const shell = require('electron').shell
|
|
||||||
shell.openExternal(url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,8 +14,6 @@ import WatchVideoLiveChat from '../../components/watch-video-live-chat/watch-vid
|
||||||
import WatchVideoPlaylist from '../../components/watch-video-playlist/watch-video-playlist.vue'
|
import WatchVideoPlaylist from '../../components/watch-video-playlist/watch-video-playlist.vue'
|
||||||
import WatchVideoRecommendations from '../../components/watch-video-recommendations/watch-video-recommendations.vue'
|
import WatchVideoRecommendations from '../../components/watch-video-recommendations/watch-video-recommendations.vue'
|
||||||
|
|
||||||
const remote = require('@electron/remote')
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'Watch',
|
name: 'Watch',
|
||||||
components: {
|
components: {
|
||||||
|
@ -931,7 +929,7 @@ export default Vue.extend({
|
||||||
const countDownIntervalId = setInterval(showCountDownMessage, 1000)
|
const countDownIntervalId = setInterval(showCountDownMessage, 1000)
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRouteChange: function () {
|
handleRouteChange: async function () {
|
||||||
clearTimeout(this.playNextTimeout)
|
clearTimeout(this.playNextTimeout)
|
||||||
|
|
||||||
this.handleWatchProgress()
|
this.handleWatchProgress()
|
||||||
|
@ -961,7 +959,7 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.removeVideoMetaFiles) {
|
if (this.removeVideoMetaFiles) {
|
||||||
const userData = remote.app.getPath('userData')
|
const userData = await this.getUserDataPath()
|
||||||
if (this.isDev) {
|
if (this.isDev) {
|
||||||
const dashFileLocation = `dashFiles/${this.videoId}.xml`
|
const dashFileLocation = `dashFiles/${this.videoId}.xml`
|
||||||
const vttFileLocation = `storyboards/${this.videoId}.vtt`
|
const vttFileLocation = `storyboards/${this.videoId}.vtt`
|
||||||
|
@ -1004,9 +1002,9 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createLocalDashManifest: function (formats) {
|
createLocalDashManifest: async function (formats) {
|
||||||
const xmlData = ytDashGen.generate_dash_file_from_formats(formats, this.videoLengthSeconds)
|
const xmlData = ytDashGen.generate_dash_file_from_formats(formats, this.videoLengthSeconds)
|
||||||
const userData = remote.app.getPath('userData')
|
const userData = await this.getUserDataPath()
|
||||||
let fileLocation
|
let fileLocation
|
||||||
let uriSchema
|
let uriSchema
|
||||||
if (this.isDev) {
|
if (this.isDev) {
|
||||||
|
@ -1076,8 +1074,8 @@ export default Vue.extend({
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// TODO: MAKE A VARIABLE WHICH CAN CHOOSE BETWEEN STROYBOARD ARRAY ELEMENTS
|
// TODO: MAKE A VARIABLE WHICH CAN CHOOSE BETWEEN STROYBOARD ARRAY ELEMENTS
|
||||||
this.buildVTTFileLocally(storyboardArray[1]).then((results) => {
|
this.buildVTTFileLocally(storyboardArray[1]).then(async (results) => {
|
||||||
const userData = remote.app.getPath('userData')
|
const userData = await this.getUserDataPath()
|
||||||
let fileLocation
|
let fileLocation
|
||||||
let uriSchema
|
let uriSchema
|
||||||
|
|
||||||
|
@ -1195,7 +1193,8 @@ export default Vue.extend({
|
||||||
'showToast',
|
'showToast',
|
||||||
'buildVTTFileLocally',
|
'buildVTTFileLocally',
|
||||||
'updateHistory',
|
'updateHistory',
|
||||||
'updateWatchProgress'
|
'updateWatchProgress',
|
||||||
|
'getUserDataPath'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue