Merge branch 'development'
This commit is contained in:
commit
5fd154fa08
|
@ -147,7 +147,7 @@ jobs:
|
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: https://uploads.github.com/repos/FreeTubeApp/FreeTube/releases/${{ secrets.UPLOAD_ID }}/assets{?name,label}
|
||||
asset_name: freetube-${{ env.PACKAGE_VERSION }}-win-x64-portable
|
||||
asset_name: freetube-${{ env.PACKAGE_VERSION }}-win-x64-portable.zip
|
||||
asset_path: build/freetube-${{ env.PACKAGE_VERSION }}-win.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
|
|
|
@ -20,3 +20,4 @@ coverage
|
|||
__coverage__
|
||||
csak-timelog.json
|
||||
.idea/
|
||||
debug/
|
||||
|
|
13
README.md
13
README.md
|
@ -14,11 +14,11 @@ addressed.
|
|||
|
||||
### Browser Extension
|
||||
|
||||
Download our browser extension so that you can click on videos in your browser and have them automatically open up in FreeTube.
|
||||
FreeTube is supported by the [Privacy Redirect](https://github.com/SimonBrazell/privacy-redirect) extension, which will allow you to open YouTube links into FreeTube. You must enable the option within the advanced settings for it to work.
|
||||
|
||||
[Download for Firefox](https://addons.mozilla.org/en-US/firefox/addon/freetube-redirect/)
|
||||
Download Privacy Redirect for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/privacy-redirect/) or [Google Chrome](https://chrome.google.com/webstore/detail/privacy-redirect/pmcmeagblkinmogikoikkdjiligflglb).
|
||||
|
||||
[Instructions for Google Chrome](https://github.com/FreeTubeApp/FreeTube/wiki/Browser-Extension)
|
||||
If you have issues with the extension working with FreeTube, please create an issue in this repository instead of the extension repository.
|
||||
|
||||
## How does it work?
|
||||
FreeTube uses a built in extractor to grab and serve data / videos. The [Invidious API](https://github.com/iv-org/invidious) can also optionally be used. FreeTube does not use any official APIs to obtain data. While YouTube can still see your video requests, it can no
|
||||
|
@ -34,6 +34,7 @@ to hide your IP while using FreeTube.
|
|||
* Two extractor APIs to choose from (Built in or Invidious)
|
||||
* Subscribe to channels without an account
|
||||
* Local subscriptions, history, and saved videos
|
||||
* Organize your subscriptions into "Profiles" to create a more focused feed
|
||||
* Export & import subscriptions
|
||||
* Open videos from your browser directly into FreeTube (with extension)
|
||||
* Mini Player
|
||||
|
@ -47,12 +48,12 @@ to hide your IP while using FreeTube.
|
|||
|
||||
[FreeTube Website](https://freetubeapp.io/#download)
|
||||
|
||||
Flatpak on Flathub: [Download](https://flathub.org/apps/details/io.freetubeapp.FreeTube) [Source](https://github.com/flathub/io.freetubeapp.FreeTube)
|
||||
|
||||
### Unofficial Downloads
|
||||
|
||||
These builds are maintained by the community. While they should be safe, download at your own risk. There may be issues with using these versus the official builds. Any issues specific with these builds should be sent to their respective maintainer.
|
||||
|
||||
Flatpak on Flathub: [Download](https://flathub.org/apps/details/io.freetubeapp.FreeTube) [Source](https://github.com/flathub/io.freetubeapp.FreeTube)
|
||||
|
||||
Arch User Repository (AUR): [Download](https://aur.archlinux.org/packages/freetube-bin/)
|
||||
|
||||
Chocolatey: [Download](https://chocolatey.org/packages/freetube/)
|
||||
|
@ -87,7 +88,7 @@ We are actively looking for translations! We use Weblate to make it easy for tr
|
|||
|
||||
## Contact
|
||||
|
||||
If you ever have any questions, feel free to make an issue here on GitHub. Alternatively, you can email me at FreeTubeApp@protonmail.com or you can join our [Matrix Community](https://riot.im/app/#/group/+freetube:matrix.org). Don't forget to check out the [rules](https://github.com/FreeTubeApp/FreeTube/wiki/Matrix-Server-Info-&-Rules) before joining.
|
||||
If you ever have any questions, feel free to make an issue here on GitHub. Alternatively, you can email me at FreeTubeApp@protonmail.com or you can join our [Matrix Community](https://matrix.to/#/+freetube:matrix.org). Don't forget to check out the [rules](https://github.com/FreeTubeApp/FreeTube/wiki/Matrix-Server-Info-&-Rules) before joining.
|
||||
|
||||
You can also stay up to date by reading the [FreeTube Blog](https://write.as/freetube/). [View the welcome blog](https://write.as/freetube/welcome-to-freetube-blogs).
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
67
package.json
67
package.json
|
@ -8,23 +8,24 @@
|
|||
"url": "https://github.com/FreeTubeApp/FreeTube/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||
"@fortawesome/vue-fontawesome": "^2.0.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.34",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.2",
|
||||
"@fortawesome/vue-fontawesome": "^2.0.2",
|
||||
"@silvermine/videojs-quality-selector": "^1.2.4",
|
||||
"autolinker": "^3.14.2",
|
||||
"bulma-pro": "^0.2.0",
|
||||
"dateformat": "^4.3.1",
|
||||
"electron-context-menu": "^2.3.0",
|
||||
"dateformat": "^4.4.1",
|
||||
"electron-context-menu": "^2.4.0",
|
||||
"jquery": "^3.5.1",
|
||||
"js-yaml": "^3.14.1",
|
||||
"js-yaml": "^4.0.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.uniqwith": "^4.5.0",
|
||||
"markdown": "^0.5.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"nedb": "^1.8.0",
|
||||
"opml-to-json": "0.0.3",
|
||||
"opml-to-json": "1.0.1",
|
||||
"rss-parser": "^3.10.0",
|
||||
"video.js": "7.10.2",
|
||||
"videojs-abloop": "^1.2.0",
|
||||
|
@ -35,74 +36,74 @@
|
|||
"videojs-vtt-thumbnails-freetube": "0.0.15",
|
||||
"vue": "^2.6.12",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-i18n": "^8.22.2",
|
||||
"vue-observe-visibility": "^0.4.6",
|
||||
"vue-i18n": "^8.22.3",
|
||||
"vue-observe-visibility": "^1.0.0",
|
||||
"vue-router": "^3.4.9",
|
||||
"vuex": "^3.6.0",
|
||||
"xml2json": "^0.12.0",
|
||||
"youtube-chat": "^1.1.0",
|
||||
"youtube-suggest": "^1.1.0",
|
||||
"yt-channel-info": "^1.1.4",
|
||||
"yt-comment-scraper": "^1.3.10",
|
||||
"yt-channel-info": "^1.2.0",
|
||||
"yt-comment-scraper": "^1.3.11",
|
||||
"yt-dash-manifest-generator": "^1.1.0",
|
||||
"yt-trending-scraper": "^1.0.4",
|
||||
"yt-xml2vtt": "^1.1.3",
|
||||
"ytdl-core": "^4.2.0",
|
||||
"ytpl": "^2.0.3",
|
||||
"ytsr": "^3.0.0"
|
||||
"yt-trending-scraper": "^1.0.5",
|
||||
"yt-xml2vtt": "^1.2.0",
|
||||
"ytdl-core": "^4.4.3",
|
||||
"ytpl": "^2.0.4",
|
||||
"ytsr": "^3.2.1"
|
||||
},
|
||||
"description": "A private YouTube client",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
|
||||
"@babel/preset-env": "^7.12.10",
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@typescript-eslint/eslint-plugin": "^4.10.0",
|
||||
"@typescript-eslint/parser": "^4.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.13.0",
|
||||
"@typescript-eslint/parser": "^4.13.0",
|
||||
"acorn": "^8.0.4",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"copy-webpack-plugin": "6.4.0",
|
||||
"css-loader": "^5.0.1",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^11.1.0",
|
||||
"electron": "^11.1.1",
|
||||
"electron-builder": "^22.9.1",
|
||||
"electron-builder-squirrel-windows": "^22.10.3",
|
||||
"electron-debug": "^3.1.0",
|
||||
"electron-builder-squirrel-windows": "^22.10.4",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-rebuild": "^2.3.4",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-prettier": "^7.0.0",
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.3.0",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"eslint-plugin-vue": "^7.2.0",
|
||||
"eslint-plugin-vue": "^7.4.1",
|
||||
"fast-glob": "^3.2.4",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"jest": "^26.6.3",
|
||||
"mini-css-extract-plugin": "^1.3.3",
|
||||
"mini-css-extract-plugin": "^1.3.4",
|
||||
"node-abi": "^2.19.3",
|
||||
"node-loader": "^1.0.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.2.1",
|
||||
"sass": "^1.30.0",
|
||||
"sass-loader": "^10.1.0",
|
||||
"sass": "^1.32.4",
|
||||
"sass-loader": "^10.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"tree-kill": "1.2.2",
|
||||
"typescript": "^4.1.3",
|
||||
"url-loader": "^4.1.1",
|
||||
"vue-devtools": "^5.1.4",
|
||||
"vue-eslint-parser": "^7.3.0",
|
||||
"vue-loader": "^15.9.5",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"webpack": "4.44.2",
|
||||
"webpack-cli": "3.3.12",
|
||||
"webpack-dev-server": "^3.11.0"
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"main": "./dist/main.js",
|
||||
|
@ -142,5 +143,5 @@
|
|||
"test": "run-s rebuild:node pack:workers jest",
|
||||
"test:watch": "run-s rebuild:node pack:workers jest:watch"
|
||||
},
|
||||
"version": "0.10.0"
|
||||
"version": "0.11.0"
|
||||
}
|
||||
|
|
|
@ -65,21 +65,57 @@ if (!isDev) {
|
|||
})
|
||||
|
||||
app.on('ready', (event, commandLine, workingDirectory) => {
|
||||
settingsDb.findOne({
|
||||
_id: 'disableSmoothScrolling'
|
||||
settingsDb.find({
|
||||
$or: [
|
||||
{ _id: 'disableSmoothScrolling' },
|
||||
{ _id: 'useProxy' },
|
||||
{ _id: 'proxyProtocol' },
|
||||
{ _id: 'proxyHostname' },
|
||||
{ _id: 'proxyPort' }
|
||||
]
|
||||
}, function (err, doc) {
|
||||
if (err) {
|
||||
app.exit(0)
|
||||
return
|
||||
}
|
||||
|
||||
if (doc !== null && doc.value) {
|
||||
let disableSmoothScrolling = false
|
||||
let useProxy = false
|
||||
let proxyProtocol = 'socks5'
|
||||
let proxyHostname = '127.0.0.1'
|
||||
let proxyPort = '9050'
|
||||
|
||||
if (typeof doc === 'object' && doc.length > 0) {
|
||||
doc.forEach((dbItem) => {
|
||||
switch (dbItem._id) {
|
||||
case 'disableSmoothScrolling':
|
||||
disableSmoothScrolling = dbItem.value
|
||||
break
|
||||
case 'useProxy':
|
||||
useProxy = dbItem.value
|
||||
break
|
||||
case 'proxyProtocol':
|
||||
proxyProtocol = dbItem.value
|
||||
break
|
||||
case 'proxyHostname':
|
||||
proxyHostname = dbItem.value
|
||||
break
|
||||
case 'proxyPort':
|
||||
proxyPort = dbItem.value
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (disableSmoothScrolling) {
|
||||
app.commandLine.appendSwitch('disable-smooth-scrolling')
|
||||
} else {
|
||||
app.commandLine.appendSwitch('enable-smooth-scrolling')
|
||||
}
|
||||
|
||||
createWindow()
|
||||
const proxyUrl = `${proxyProtocol}://${proxyHostname}:${proxyPort}`
|
||||
|
||||
createWindow(useProxy, proxyUrl)
|
||||
|
||||
if (isDev) {
|
||||
installDevTools()
|
||||
|
@ -99,21 +135,57 @@ if (!isDev) {
|
|||
})
|
||||
|
||||
app.on('ready', () => {
|
||||
settingsDb.findOne({
|
||||
_id: 'disableSmoothScrolling'
|
||||
settingsDb.find({
|
||||
$or: [
|
||||
{ _id: 'disableSmoothScrolling' },
|
||||
{ _id: 'useProxy' },
|
||||
{ _id: 'proxyProtocol' },
|
||||
{ _id: 'proxyHostname' },
|
||||
{ _id: 'proxyPort' }
|
||||
]
|
||||
}, function (err, doc) {
|
||||
if (err) {
|
||||
app.exit(0)
|
||||
return
|
||||
}
|
||||
|
||||
if (doc !== null && doc.value) {
|
||||
let disableSmoothScrolling = false
|
||||
let useProxy = false
|
||||
let proxyProtocol = 'socks5'
|
||||
let proxyHostname = '127.0.0.1'
|
||||
let proxyPort = '9050'
|
||||
|
||||
if (typeof doc === 'object' && doc.length > 0) {
|
||||
doc.forEach((dbItem) => {
|
||||
switch (dbItem._id) {
|
||||
case 'disableSmoothScrolling':
|
||||
disableSmoothScrolling = dbItem.value
|
||||
break
|
||||
case 'useProxy':
|
||||
useProxy = dbItem.value
|
||||
break
|
||||
case 'proxyProtocol':
|
||||
proxyProtocol = dbItem.value
|
||||
break
|
||||
case 'proxyHostname':
|
||||
proxyHostname = dbItem.value
|
||||
break
|
||||
case 'proxyPort':
|
||||
proxyPort = dbItem.value
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (disableSmoothScrolling) {
|
||||
app.commandLine.appendSwitch('disable-smooth-scrolling')
|
||||
} else {
|
||||
app.commandLine.appendSwitch('enable-smooth-scrolling')
|
||||
}
|
||||
|
||||
createWindow()
|
||||
const proxyUrl = `${proxyProtocol}://${proxyHostname}:${proxyPort}`
|
||||
|
||||
createWindow(useProxy, proxyUrl)
|
||||
|
||||
if (isDev) {
|
||||
installDevTools()
|
||||
|
@ -137,7 +209,7 @@ async function installDevTools () {
|
|||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
function createWindow (useProxy = false, proxyUrl = '') {
|
||||
/**
|
||||
* Initial window options
|
||||
*/
|
||||
|
@ -164,6 +236,12 @@ function createWindow () {
|
|||
height: 800
|
||||
})
|
||||
|
||||
if (useProxy) {
|
||||
mainWindow.webContents.session.setProxy({
|
||||
proxyRules: proxyUrl
|
||||
})
|
||||
}
|
||||
|
||||
settingsDb.findOne({
|
||||
_id: 'bounds'
|
||||
}, function (err, doc) {
|
||||
|
@ -264,6 +342,17 @@ function createWindow () {
|
|||
mainWindow.close()
|
||||
createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('enableProxy', (event, url) => {
|
||||
console.log(url)
|
||||
mainWindow.webContents.session.setProxy({
|
||||
proxyRules: url
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.on('disableProxy', () => {
|
||||
mainWindow.webContents.session.setProxy({})
|
||||
})
|
||||
}
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
@ -306,7 +395,8 @@ app.on('open-url', (event, url) => {
|
|||
})
|
||||
|
||||
/*
|
||||
* Check if we were passed a freetube:// URL on process startup (linux/win)
|
||||
* Check if an argument was passed and send it over to the GUI (Linux / Windows).
|
||||
* Remove freetube:// protocol if present
|
||||
*/
|
||||
const url = getLinkUrl(process.argv)
|
||||
if (url) {
|
||||
|
@ -318,12 +408,11 @@ function baseUrl(arg) {
|
|||
}
|
||||
|
||||
function getLinkUrl(argv) {
|
||||
for (const arg of argv) {
|
||||
if (arg.indexOf('freetube://') !== -1) {
|
||||
return baseUrl(arg)
|
||||
}
|
||||
if (argv.length > 1) {
|
||||
return baseUrl(argv[argv.length - 1])
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -88,6 +88,7 @@ export default Vue.extend({
|
|||
this.$store.dispatch('grabUserSettings')
|
||||
this.$store.dispatch('grabHistory')
|
||||
this.$store.dispatch('grabAllProfiles', this.$t('Profile.All Channels'))
|
||||
this.$store.dispatch('grabAllPlaylists')
|
||||
this.$store.commit('setUsingElectron', useElectron)
|
||||
this.checkThemeSettings()
|
||||
this.checkLocale()
|
||||
|
@ -172,7 +173,15 @@ export default Vue.extend({
|
|||
|
||||
const message = this.$t('Version $ is now available! Click for more details')
|
||||
this.updateBannerMessage = message.replace('$', versionNumber)
|
||||
if (version < versionNumber) {
|
||||
|
||||
const appVersion = version.split('.')
|
||||
const latestVersion = versionNumber.split('.')
|
||||
|
||||
if (parseInt(appVersion[0]) < parseInt(latestVersion[0])) {
|
||||
this.showUpdatesBanner = true
|
||||
} else if (parseInt(appVersion[1]) < parseInt(latestVersion[1])) {
|
||||
this.showUpdatesBanner = true
|
||||
} else if (parseInt(appVersion[2]) < parseInt(latestVersion[2])) {
|
||||
this.showUpdatesBanner = true
|
||||
}
|
||||
}).fail((xhr, textStatus, error) => {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="20px" height="20px"><path class="loop" d="M12 4V2.21c0-.45-.54-.67-.85-.35l-2.8 2.79c-.2.2-.2.51 0 .71l2.79 2.79c.32.31.86.09.86-.36V6c3.31 0 6 2.69 6 6 0 .79-.15 1.56-.44 2.25-.15.36-.04.77.23 1.04.51.51 1.37.33 1.64-.34.37-.91.57-1.91.57-2.95 0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-.79.15-1.56.44-2.25.15-.36.04-.77-.23-1.04-.51-.51-1.37-.33-1.64.34C4.2 9.96 4 10.96 4 12c0 4.42 3.58 8 8 8v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.31-.85-.09-.85.36V18z"/></svg>
|
After Width: | Height: | Size: 577 B |
|
@ -78,6 +78,12 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
openProfileSettings: function () {
|
||||
this.$router.push({
|
||||
path: '/settings/profile/'
|
||||
})
|
||||
},
|
||||
|
||||
importSubscriptions: function (option) {
|
||||
this.showImportSubscriptionsPrompt = false
|
||||
|
||||
|
@ -265,7 +271,11 @@ export default Vue.extend({
|
|||
return sub.id === subscription.id || sub.name === subscription.name
|
||||
})
|
||||
|
||||
if (subExists === -1) {
|
||||
const subDuplicateExists = subscriptions.findIndex((sub) => {
|
||||
return sub.id === subscription.id || sub.name === subscription.name
|
||||
})
|
||||
|
||||
if (subExists === -1 && subDuplicateExists === -1) {
|
||||
subscriptions.push(subscription)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,22 @@
|
|||
@click="exportHistory"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<ft-flex-box>
|
||||
<a
|
||||
class="center"
|
||||
href="https://github.com/FreeTubeApp/FreeTube/wiki/Importing-Your-YouTube-Subscriptions"
|
||||
>
|
||||
<p>
|
||||
{{ $t("Settings.Data Settings.How do I import my subscriptions?") }}
|
||||
</p>
|
||||
</a>
|
||||
</ft-flex-box>
|
||||
<ft-flex-box>
|
||||
<ft-button
|
||||
:label="$t('Settings.Data Settings.Manage Subscriptions')"
|
||||
@click="openProfileSettings"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<ft-prompt
|
||||
v-if="showImportSubscriptionsPrompt"
|
||||
:label="$t('Settings.Data Settings.Select Import Type')"
|
||||
|
|
|
@ -39,13 +39,15 @@ export default Vue.extend({
|
|||
},
|
||||
hideLiveChat: function () {
|
||||
return this.$store.getters.getHideLiveChat
|
||||
},
|
||||
hideActiveSubscriptions: function () {
|
||||
return this.$store.getters.getHideActiveSubscriptions
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleHideRecommendedVideos: function (value) {
|
||||
if (value) {
|
||||
this.updatePlayNextVideo(false)
|
||||
this.updateDefaultTheatreMode(true)
|
||||
}
|
||||
|
||||
this.updateHideRecommendedVideos(value)
|
||||
|
@ -60,6 +62,7 @@ export default Vue.extend({
|
|||
'updateHideTrendingVideos',
|
||||
'updateHidePopularVideos',
|
||||
'updateHideLiveChat',
|
||||
'updateHideActiveSubscriptions',
|
||||
'updatePlayNextVideo',
|
||||
'updateDefaultTheatreMode'
|
||||
])
|
||||
|
|
|
@ -33,6 +33,12 @@
|
|||
:default-value="hideCommentLikes"
|
||||
@change="updateHideCommentLikes"
|
||||
/>
|
||||
<ft-toggle-switch
|
||||
:label="$t('Settings.Distraction Free Settings.Hide Active Subscriptions')"
|
||||
:compact="true"
|
||||
:default-value="hideActiveSubscriptions"
|
||||
@change="updateHideActiveSubscriptions"
|
||||
/>
|
||||
</div>
|
||||
<div class="switchColumn">
|
||||
<ft-toggle-switch
|
||||
|
|
|
@ -52,6 +52,9 @@
|
|||
&:active
|
||||
background-color: var(--accent-color-active)
|
||||
|
||||
&.favorite
|
||||
color: var(--favorite-icon-color)
|
||||
|
||||
.iconDropdown
|
||||
display: none
|
||||
position: absolute
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ft-tooltip
|
||||
v-if="tooltip !== ''"
|
||||
class="selectTooltip"
|
||||
position="right"
|
||||
position="bottom"
|
||||
:tooltip="tooltip"
|
||||
/>
|
||||
</label>
|
||||
|
|
|
@ -57,6 +57,10 @@ export default Vue.extend({
|
|||
this.channelLink = this.data.authorUrl
|
||||
this.playlistLink = this.data.playlistId
|
||||
this.videoCount = this.data.videoCount
|
||||
|
||||
if (this.data.proxyThumbnail === false) {
|
||||
this.thumbnail = this.data.playlistThumbnail
|
||||
}
|
||||
},
|
||||
|
||||
parseLocalData: function () {
|
||||
|
|
|
@ -161,6 +161,26 @@ export default Vue.extend({
|
|||
},
|
||||
hideVideoViews: function () {
|
||||
return this.$store.getters.getHideVideoViews
|
||||
},
|
||||
|
||||
addWatchedStyle: function () {
|
||||
return this.watched && !this.inHistory
|
||||
},
|
||||
|
||||
favoritesPlaylist: function () {
|
||||
return this.$store.getters.getFavorites
|
||||
},
|
||||
|
||||
inFavoritesPlaylist: function () {
|
||||
const index = this.favoritesPlaylist.videos.findIndex((video) => {
|
||||
return video.videoId === this.id
|
||||
})
|
||||
|
||||
return index !== -1
|
||||
},
|
||||
|
||||
favoriteIconTheme: function () {
|
||||
return this.inFavoritesPlaylist ? 'base favorite' : 'base'
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
|
@ -169,10 +189,11 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
toggleSave: function () {
|
||||
console.log('TODO: ft-list-video method toggleSave')
|
||||
this.showToast({
|
||||
message: this.$t('Saving videos are currently not available. Please wait for a future update')
|
||||
})
|
||||
if (this.inFavoritesPlaylist) {
|
||||
this.removeFromPlaylist()
|
||||
} else {
|
||||
this.addToPlaylist()
|
||||
}
|
||||
},
|
||||
|
||||
handleOptionsClick: function (option) {
|
||||
|
@ -392,11 +413,54 @@ export default Vue.extend({
|
|||
this.watched = false
|
||||
},
|
||||
|
||||
addToPlaylist: function () {
|
||||
const videoData = {
|
||||
videoId: this.id,
|
||||
title: this.title,
|
||||
author: this.channelName,
|
||||
authorId: this.channelId,
|
||||
published: '',
|
||||
description: this.description,
|
||||
viewCount: this.viewCount,
|
||||
lengthSeconds: this.data.lengthSeconds,
|
||||
timeAdded: new Date().getTime(),
|
||||
isLive: false,
|
||||
paid: false,
|
||||
type: 'video'
|
||||
}
|
||||
|
||||
const payload = {
|
||||
playlistName: 'Favorites',
|
||||
videoData: videoData
|
||||
}
|
||||
|
||||
this.addVideo(payload)
|
||||
|
||||
this.showToast({
|
||||
message: this.$t('Video.Video has been saved')
|
||||
})
|
||||
},
|
||||
|
||||
removeFromPlaylist: function () {
|
||||
const payload = {
|
||||
playlistName: 'Favorites',
|
||||
videoId: this.id
|
||||
}
|
||||
|
||||
this.removeVideo(payload)
|
||||
|
||||
this.showToast({
|
||||
message: this.$t('Video.Video has been removed from your saved list')
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'toLocalePublicationString',
|
||||
'updateHistory',
|
||||
'removeFromHistory'
|
||||
'removeFromHistory',
|
||||
'addVideo',
|
||||
'removeVideo'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
list: (listType === 'list' || forceListType === 'list') && forceListType !== 'grid',
|
||||
grid: (listType === 'grid' || forceListType === 'list') && forceListType !== 'list',
|
||||
[appearance]: true,
|
||||
watched: watched
|
||||
watched: addWatchedStyle
|
||||
}"
|
||||
>
|
||||
<div
|
||||
|
@ -32,16 +32,16 @@
|
|||
</div>
|
||||
<ft-icon-button
|
||||
v-if="!isLive"
|
||||
:title="$t('Video.Save Video')"
|
||||
icon="star"
|
||||
class="favoritesIcon"
|
||||
theme="base"
|
||||
:theme="favoriteIconTheme"
|
||||
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
|
||||
:size="appearance === `watchPlaylistItem` ? 14 : 18"
|
||||
:class="{ favorited: isFavorited }"
|
||||
@click="toggleSave(id)"
|
||||
@click="toggleSave"
|
||||
/>
|
||||
<div
|
||||
v-if="watched"
|
||||
v-if="addWatchedStyle"
|
||||
class="videoWatched"
|
||||
>
|
||||
{{ $t("Video.Watched") }}
|
||||
|
|
|
@ -88,7 +88,7 @@ export default Vue.extend({
|
|||
if (this.searchSettings.type !== 'video') {
|
||||
const typeRadio = this.$refs.typeRadio
|
||||
typeRadio.updateSelectedValue('all')
|
||||
this.updateType('all')
|
||||
this.$store.commit('setSearchType', 'all')
|
||||
}
|
||||
this.$store.commit('setSearchTime', value)
|
||||
},
|
||||
|
@ -99,8 +99,8 @@ export default Vue.extend({
|
|||
const durationRadio = this.$refs.durationRadio
|
||||
timeRadio.updateSelectedValue('')
|
||||
durationRadio.updateSelectedValue('')
|
||||
this.updateTime('')
|
||||
this.updateDuration('')
|
||||
this.$store.commit('setSearchTime', '')
|
||||
this.$store.commit('setSearchDuration', '')
|
||||
}
|
||||
this.$store.commit('setSearchType', value)
|
||||
},
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<ft-tooltip
|
||||
v-if="tooltip !== ''"
|
||||
class="selectTooltip"
|
||||
position="bottom-left"
|
||||
:tooltip="tooltip"
|
||||
/>
|
||||
</label>
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
.button:focus + .text.bottom,
|
||||
.button:hover + .text.bottom,
|
||||
.button:hover + .text.bottom-left,
|
||||
.button:hover + .text.bottom-left,
|
||||
.button:focus + .text.top,
|
||||
.button:hover + .text.top {
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
|
@ -57,6 +59,14 @@
|
|||
transform: translate(-50%, -1em);
|
||||
}
|
||||
|
||||
.text.bottom-left {
|
||||
margin-top: 1em;
|
||||
top: 100%;
|
||||
left: -100px;
|
||||
-webkit-transform: translate(-50%, -1em);
|
||||
transform: translate(-50%, -1em);
|
||||
}
|
||||
|
||||
.text.left {
|
||||
margin-right:1em;
|
||||
right: 100%;
|
||||
|
|
|
@ -7,7 +7,7 @@ export default Vue.extend({
|
|||
position: {
|
||||
type: String,
|
||||
default: 'bottom',
|
||||
validator: (value) => value === 'bottom' || value === 'left' || value === 'right' || value === 'top'
|
||||
validator: (value) => value === 'bottom' || value === 'left' || value === 'right' || value === 'top' || value === 'bottom-left'
|
||||
},
|
||||
tooltip: {
|
||||
type: String,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
import { mapActions } from 'vuex'
|
||||
import FtCard from '../ft-card/ft-card.vue'
|
||||
|
||||
import $ from 'jquery'
|
||||
|
@ -17,6 +18,9 @@ export default Vue.extend({
|
|||
'ft-card': FtCard
|
||||
},
|
||||
beforeRouteLeave: function () {
|
||||
if (this.player !== null) {
|
||||
this.exitFullWindow()
|
||||
}
|
||||
if (this.player !== null && !this.player.isInPictureInPicture()) {
|
||||
this.player.dispose()
|
||||
this.player = null
|
||||
|
@ -24,6 +28,11 @@ export default Vue.extend({
|
|||
} else if (this.player.isInPictureInPicture()) {
|
||||
this.player.play()
|
||||
}
|
||||
|
||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||
const { powerSaveBlocker } = require('electron')
|
||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
||||
}
|
||||
},
|
||||
props: {
|
||||
format: {
|
||||
|
@ -58,6 +67,7 @@ export default Vue.extend({
|
|||
data: function () {
|
||||
return {
|
||||
id: '',
|
||||
powerSaveBlocker: null,
|
||||
volume: 1,
|
||||
player: null,
|
||||
useDash: false,
|
||||
|
@ -67,7 +77,7 @@ export default Vue.extend({
|
|||
activeSourceList: [],
|
||||
mouseTimeout: null,
|
||||
dataSetup: {
|
||||
aspectRatio: '16:9',
|
||||
fluid: true,
|
||||
nativeTextTracks: false,
|
||||
plugins: {},
|
||||
controlBar: {
|
||||
|
@ -83,6 +93,7 @@ export default Vue.extend({
|
|||
'remainingTimeDisplay',
|
||||
'customControlSpacer',
|
||||
'playbackRateMenuButton',
|
||||
'loopButton',
|
||||
'chaptersButton',
|
||||
'descriptionsButton',
|
||||
'subsCapsButton',
|
||||
|
@ -112,6 +123,10 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
usingElectron: function () {
|
||||
return this.$store.getters.getUsingElectron
|
||||
},
|
||||
|
||||
defaultPlayback: function () {
|
||||
return this.$store.getters.getDefaultPlayback
|
||||
},
|
||||
|
@ -148,14 +163,24 @@ export default Vue.extend({
|
|||
}
|
||||
|
||||
this.createFullWindowButton()
|
||||
this.createLoopButton()
|
||||
this.determineFormatType()
|
||||
this.determineMaxFramerate()
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
if (this.player !== null && !this.player.isInPictureInPicture()) {
|
||||
this.player.dispose()
|
||||
this.player = null
|
||||
clearTimeout(this.mouseTimeout)
|
||||
if (this.player !== null) {
|
||||
this.exitFullWindow()
|
||||
|
||||
if (!this.player.isInPictureInPicture()) {
|
||||
this.player.dispose()
|
||||
this.player = null
|
||||
clearTimeout(this.mouseTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||
const { powerSaveBlocker } = require('electron')
|
||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -170,7 +195,9 @@ export default Vue.extend({
|
|||
this.player = videojs(videoPlayer, {
|
||||
html5: {
|
||||
vhs: {
|
||||
limitRenditionByPlayerDimensions: false
|
||||
limitRenditionByPlayerDimensions: false,
|
||||
smoothQualityChange: false,
|
||||
allowSeeksWithinUnsafeLiveWindow: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -217,6 +244,7 @@ export default Vue.extend({
|
|||
|
||||
this.player.on('ready', function () {
|
||||
v.$emit('ready')
|
||||
v.checkAspectRatio()
|
||||
})
|
||||
|
||||
this.player.on('ended', function () {
|
||||
|
@ -226,6 +254,39 @@ export default Vue.extend({
|
|||
this.player.on('error', function (error, message) {
|
||||
v.$emit('error', error.target.player.error_)
|
||||
})
|
||||
|
||||
this.player.on('play', function () {
|
||||
if (this.usingElectron) {
|
||||
const { powerSaveBlocker } = require('electron')
|
||||
|
||||
this.powerSaveBlocker = powerSaveBlocker.start('prevent-display-sleep')
|
||||
}
|
||||
})
|
||||
|
||||
this.player.on('pause', function () {
|
||||
if (this.usingElectron && this.powerSaveBlocker !== null) {
|
||||
const { powerSaveBlocker } = require('electron')
|
||||
powerSaveBlocker.stop(this.powerSaveBlocker)
|
||||
this.powerSaveBlocker = null
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
checkAspectRatio() {
|
||||
const videoWidth = this.player.videoWidth()
|
||||
const videoHeight = this.player.videoHeight()
|
||||
|
||||
if (videoWidth === 0 || videoHeight === 0) {
|
||||
setTimeout(() => {
|
||||
this.checkAspectRatio()
|
||||
}, 200)
|
||||
return
|
||||
}
|
||||
|
||||
if (videoWidth < videoHeight) {
|
||||
this.player.fluid(false)
|
||||
this.player.aspectRatio('16:9')
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -268,7 +329,6 @@ export default Vue.extend({
|
|||
}
|
||||
fs.readFile(this.dashSrc[0].url, (err, data) => {
|
||||
if (err) {
|
||||
console.log('caught the error')
|
||||
this.maxFramerate = 60
|
||||
return
|
||||
}
|
||||
|
@ -504,7 +564,53 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
|
||||
createFullWindowButton: function() {
|
||||
createLoopButton: function () {
|
||||
const v = this
|
||||
const VjsButton = videojs.getComponent('Button')
|
||||
const loopButton = videojs.extend(VjsButton, {
|
||||
constructor: function(player, options) {
|
||||
VjsButton.call(this, player, options)
|
||||
},
|
||||
handleClick: function() {
|
||||
v.toggleVideoLoop()
|
||||
},
|
||||
createControlTextEl: function (button) {
|
||||
return $(button).html($('<div id="loopButton" class="vjs-icon-loop loop-white vjs-button loopWhite"></div>')
|
||||
.attr('title', 'Toggle Loop'))
|
||||
}
|
||||
})
|
||||
videojs.registerComponent('loopButton', loopButton)
|
||||
},
|
||||
|
||||
toggleVideoLoop: async function () {
|
||||
if (!this.player.loop()) {
|
||||
const currentTheme = localStorage.getItem('mainColor')
|
||||
const colorNames = this.$store.state.utils.colorClasses
|
||||
const colorValues = this.$store.state.utils.colorValues
|
||||
|
||||
const nameIndex = colorNames.findIndex((color) => {
|
||||
return color === currentTheme
|
||||
})
|
||||
|
||||
const themeTextColor = await this.calculateColorLuminance(colorValues[nameIndex])
|
||||
|
||||
$('#loopButton').addClass('vjs-icon-loop-active')
|
||||
|
||||
if (themeTextColor === '#000000') {
|
||||
$('#loopButton').addClass('loop-black')
|
||||
$('#loopButton').removeClass('loop-white')
|
||||
}
|
||||
|
||||
this.player.loop(true)
|
||||
} else {
|
||||
$('#loopButton').removeClass('vjs-icon-loop-active')
|
||||
$('#loopButton').removeClass('loop-black')
|
||||
$('#loopButton').addClass('loop-white')
|
||||
this.player.loop(false)
|
||||
}
|
||||
},
|
||||
|
||||
createFullWindowButton: function () {
|
||||
const v = this
|
||||
const VjsButton = videojs.getComponent('Button')
|
||||
const fullWindowButton = videojs.extend(VjsButton, {
|
||||
|
@ -622,6 +728,10 @@ export default Vue.extend({
|
|||
}
|
||||
}
|
||||
|
||||
if (event.ctrlKey) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.player !== null) {
|
||||
switch (event.which) {
|
||||
case 32:
|
||||
|
@ -794,6 +904,10 @@ export default Vue.extend({
|
|||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'calculateColorLuminance'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
<ft-toggle-switch
|
||||
:label="$t('Settings.Player Settings.Enable Theatre Mode by Default')"
|
||||
:compact="true"
|
||||
:disabled="hideRecommendedVideos"
|
||||
:default-value="defaultTheatreMode"
|
||||
@change="updateDefaultTheatreMode"
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 85%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 680px) {
|
||||
.card {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.subscriptionSettingsFlexBox {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
import Vue from 'vue'
|
||||
import $ from 'jquery'
|
||||
import { mapActions } from 'vuex'
|
||||
import FtCard from '../ft-card/ft-card.vue'
|
||||
import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
|
||||
import FtButton from '../ft-button/ft-button.vue'
|
||||
import FtSelect from '../ft-select/ft-select.vue'
|
||||
import FtInput from '../ft-input/ft-input.vue'
|
||||
import FtLoader from '../ft-loader/ft-loader.vue'
|
||||
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||
|
||||
import electron from 'electron'
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'ProxySettings',
|
||||
components: {
|
||||
'ft-card': FtCard,
|
||||
'ft-toggle-switch': FtToggleSwitch,
|
||||
'ft-button': FtButton,
|
||||
'ft-select': FtSelect,
|
||||
'ft-input': FtInput,
|
||||
'ft-loader': FtLoader,
|
||||
'ft-flex-box': FtFlexBox
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
isLoading: false,
|
||||
dataAvailable: false,
|
||||
proxyTestUrl: 'https://api.ipify.org?format=json',
|
||||
proxyTestUrl1: 'https://freegeoip.app/json/',
|
||||
proxyId: '',
|
||||
proxyCountry: '',
|
||||
proxyRegion: '',
|
||||
proxyCity: '',
|
||||
proxyHost: '',
|
||||
protocolNames: [
|
||||
'HTTP',
|
||||
'HTTPS',
|
||||
'SOCKS4',
|
||||
'SOCKS5'
|
||||
],
|
||||
protocolValues: [
|
||||
'http',
|
||||
'https',
|
||||
'socks4',
|
||||
'socks5'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
useProxy: function () {
|
||||
return this.$store.getters.getUseProxy
|
||||
},
|
||||
proxyProtocol: function () {
|
||||
return this.$store.getters.getProxyProtocol
|
||||
},
|
||||
proxyHostname: function () {
|
||||
return this.$store.getters.getProxyHostname
|
||||
},
|
||||
proxyPort: function () {
|
||||
return this.$store.getters.getProxyPort
|
||||
},
|
||||
proxyUrl: function () {
|
||||
return `${this.proxyProtocol}://${this.proxyHostname}:${this.proxyPort}`
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.debounceEnableProxy = debounce(this.enableProxy, 200)
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
if (this.proxyHostname === '') {
|
||||
this.updateProxyHostname('127.0.0.1')
|
||||
}
|
||||
|
||||
if (this.proxyPort === '') {
|
||||
this.updateProxyPort('9050')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleUpdateProxy: function (value) {
|
||||
if (value) {
|
||||
this.enableProxy()
|
||||
} else {
|
||||
this.disableProxy()
|
||||
}
|
||||
this.updateUseProxy(value)
|
||||
},
|
||||
|
||||
handleUpdateProxyProtocol: function (value) {
|
||||
if (this.useProxy) {
|
||||
this.enableProxy()
|
||||
}
|
||||
this.updateProxyProtocol(value)
|
||||
},
|
||||
|
||||
handleUpdateProxyHostname: function (value) {
|
||||
if (this.useProxy) {
|
||||
this.debounceEnableProxy()
|
||||
}
|
||||
this.updateProxyHostname(value)
|
||||
},
|
||||
|
||||
handleUpdateProxyPort: function (value) {
|
||||
if (this.useProxy) {
|
||||
this.debounceEnableProxy()
|
||||
}
|
||||
this.updateProxyPort(value)
|
||||
},
|
||||
|
||||
enableProxy: function () {
|
||||
electron.ipcRenderer.send('enableProxy', this.proxyUrl)
|
||||
},
|
||||
|
||||
disableProxy: function () {
|
||||
electron.ipcRenderer.send('disableProxy')
|
||||
},
|
||||
|
||||
testProxy: function () {
|
||||
this.isLoading = true
|
||||
if (!this.useProxy) {
|
||||
this.enableProxy()
|
||||
}
|
||||
$.getJSON(this.proxyTestUrl1, (response) => {
|
||||
console.log(response)
|
||||
this.proxyIp = response.ip
|
||||
this.proxyCountry = response.country_name
|
||||
this.proxyRegion = response.region_name
|
||||
this.proxyCity = response.city
|
||||
this.dataAvailable = true
|
||||
}).fail((xhr, textStatus, error) => {
|
||||
console.log(xhr)
|
||||
console.log(textStatus)
|
||||
console.log(error)
|
||||
this.showToast({
|
||||
message: this.$t('Settings.Proxy Settings["Error getting network information. Is your proxy configured properly?"]')
|
||||
})
|
||||
this.dataAvailable = false
|
||||
}).always(() => {
|
||||
if (!this.useProxy) {
|
||||
this.disableProxy()
|
||||
}
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'updateUseProxy',
|
||||
'updateProxyProtocol',
|
||||
'updateProxyHostname',
|
||||
'updateProxyPort'
|
||||
])
|
||||
}
|
||||
})
|
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<ft-card
|
||||
class="relative card"
|
||||
>
|
||||
<h3
|
||||
class="videoTitle"
|
||||
>
|
||||
{{ $t("Settings.Proxy Settings.Proxy Settings") }}
|
||||
</h3>
|
||||
<ft-flex-box class="subscriptionSettingsFlexBox">
|
||||
<ft-toggle-switch
|
||||
:label="$t('Settings.Proxy Settings.Enable Tor / Proxy')"
|
||||
:default-value="useProxy"
|
||||
@change="handleUpdateProxy"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<ft-flex-box>
|
||||
<ft-select
|
||||
:placeholder="$t('Settings.Proxy Settings.Proxy Protocol')"
|
||||
:value="proxyProtocol"
|
||||
:select-names="protocolNames"
|
||||
:select-values="protocolValues"
|
||||
@change="handleUpdateProxyProtocol"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<ft-flex-box>
|
||||
<ft-input
|
||||
:placeholder="$t('Settings.Proxy Settings.Proxy Host')"
|
||||
:show-arrow="false"
|
||||
:show-label="true"
|
||||
:value="proxyHostname"
|
||||
@input="handleUpdateProxyHostname"
|
||||
/>
|
||||
<ft-input
|
||||
:placeholder="$t('Settings.Proxy Settings.Proxy Port Number')"
|
||||
:show-arrow="false"
|
||||
:show-label="true"
|
||||
:value="proxyPort"
|
||||
@input="handleUpdateProxyPort"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<p class="center">
|
||||
{{ $t('Settings.Proxy Settings.Clicking on Test Proxy will send a request to') }} https://freegeoip.app/json/
|
||||
</p>
|
||||
<ft-flex-box>
|
||||
<ft-button
|
||||
:label="$t('Settings.Proxy Settings.Test Proxy')"
|
||||
@click="testProxy"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<ft-loader
|
||||
v-if="isLoading"
|
||||
/>
|
||||
<div
|
||||
v-if="!isLoading && dataAvailable"
|
||||
class="center"
|
||||
>
|
||||
<h3>
|
||||
{{ $t('Settings.Proxy Settings.Your Info') }}
|
||||
</h3>
|
||||
<p>
|
||||
{{ $t('Settings.Proxy Settings.Ip') }}: {{ proxyIp }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('Settings.Proxy Settings.Country') }}: {{ proxyCountry }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('Settings.Proxy Settings.Region') }}: {{ proxyRegion }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('Settings.Proxy Settings.City') }}: {{ proxyCity }}
|
||||
</p>
|
||||
</div>
|
||||
</ft-card>
|
||||
</template>
|
||||
|
||||
<script src="./proxy-settings.js" />
|
||||
<style scoped src="./proxy-settings.css" />
|
|
@ -50,6 +50,9 @@ export default Vue.extend({
|
|||
},
|
||||
hideTrendingVideos: function () {
|
||||
return this.$store.getters.getHideTrendingVideos
|
||||
},
|
||||
hideActiveSubscriptions: function () {
|
||||
return this.$store.getters.getHideActiveSubscriptions
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -97,26 +97,30 @@
|
|||
</div>
|
||||
<hr>
|
||||
<div
|
||||
v-for="(channel, index) in activeSubscriptions"
|
||||
:key="index"
|
||||
class="navChannel mobileHidden"
|
||||
:title="channel.name"
|
||||
@click="goToChannel(channel.id)"
|
||||
v-if="!hideActiveSubscriptions"
|
||||
>
|
||||
<div
|
||||
class="thumbnailContainer"
|
||||
v-for="(channel, index) in activeSubscriptions"
|
||||
:key="index"
|
||||
class="navChannel mobileHidden"
|
||||
:title="channel.name"
|
||||
@click="goToChannel(channel.id)"
|
||||
>
|
||||
<img
|
||||
class="channelThumbnail"
|
||||
:src="channel.thumbnail"
|
||||
<div
|
||||
class="thumbnailContainer"
|
||||
>
|
||||
<img
|
||||
class="channelThumbnail"
|
||||
:src="channel.thumbnail"
|
||||
>
|
||||
</div>
|
||||
<p
|
||||
v-if="isOpen"
|
||||
class="navLabel"
|
||||
>
|
||||
{{ channel.name }}
|
||||
</p>
|
||||
</div>
|
||||
<p
|
||||
v-if="isOpen"
|
||||
class="navLabel"
|
||||
>
|
||||
{{ channel.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ft-flex-box>
|
||||
|
|
|
@ -7,7 +7,7 @@ import FtSelect from '../ft-select/ft-select.vue'
|
|||
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'PlayerSettings',
|
||||
name: 'SubscriptionSettings',
|
||||
components: {
|
||||
'ft-card': FtCard,
|
||||
'ft-toggle-switch': FtToggleSwitch,
|
||||
|
|
|
@ -77,7 +77,7 @@ export default Vue.extend({
|
|||
this.debounceSearchResults = debounce(this.getSearchSuggestions, 200)
|
||||
},
|
||||
methods: {
|
||||
goToSearch: function (query) {
|
||||
goToSearch: async function (query) {
|
||||
const appWidth = $(window).width()
|
||||
|
||||
if (appWidth <= 680) {
|
||||
|
@ -89,23 +89,30 @@ export default Vue.extend({
|
|||
searchInput.blur()
|
||||
}
|
||||
|
||||
this.$store.dispatch('getVideoIdFromUrl', query).then((result) => {
|
||||
if (result) {
|
||||
this.$router.push({
|
||||
path: `/watch/${result}`
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: `/search/${encodeURIComponent(query)}`,
|
||||
query: {
|
||||
sortBy: this.searchSettings.sortBy,
|
||||
time: this.searchSettings.time,
|
||||
type: this.searchSettings.type,
|
||||
duration: this.searchSettings.duration
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
const videoId = await this.$store.dispatch('getVideoIdFromUrl', query)
|
||||
const playlistId = await this.$store.dispatch('getPlaylistIdFromUrl', query)
|
||||
|
||||
console.log(playlistId)
|
||||
|
||||
if (videoId) {
|
||||
this.$router.push({
|
||||
path: `/watch/${videoId}`
|
||||
})
|
||||
} else if (playlistId) {
|
||||
this.$router.push({
|
||||
path: `/playlist/${playlistId}`
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: `/search/${encodeURIComponent(query)}`,
|
||||
query: {
|
||||
sortBy: this.searchSettings.sortBy,
|
||||
time: this.searchSettings.time,
|
||||
type: this.searchSettings.type,
|
||||
duration: this.searchSettings.duration
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.showFilters = false
|
||||
},
|
||||
|
|
|
@ -78,6 +78,18 @@ export default Vue.extend({
|
|||
downloadLinks: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
watchingPlaylist: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
theatrePossible: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
lengthSeconds: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
|
@ -111,6 +123,10 @@ export default Vue.extend({
|
|||
return this.$store.getters.getHideRecommendedVideos
|
||||
},
|
||||
|
||||
hideLiveChat: function () {
|
||||
return this.$store.getters.getHideLiveChat
|
||||
},
|
||||
|
||||
hideVideoLikesAndDislikes: function () {
|
||||
return this.$store.getters.getHideVideoLikesAndDislikes
|
||||
},
|
||||
|
@ -119,6 +135,22 @@ export default Vue.extend({
|
|||
return this.$store.getters.getHideVideoViews
|
||||
},
|
||||
|
||||
favoritesPlaylist: function () {
|
||||
return this.$store.getters.getFavorites
|
||||
},
|
||||
|
||||
inFavoritesPlaylist: function () {
|
||||
const index = this.favoritesPlaylist.videos.findIndex((video) => {
|
||||
return video.videoId === this.id
|
||||
})
|
||||
|
||||
return index !== -1
|
||||
},
|
||||
|
||||
favoriteIconTheme: function () {
|
||||
return this.inFavoritesPlaylist ? 'base favorite' : 'base'
|
||||
},
|
||||
|
||||
downloadLinkNames: function () {
|
||||
return this.downloadLinks.map((download) => {
|
||||
return download.label
|
||||
|
@ -196,6 +228,14 @@ export default Vue.extend({
|
|||
this.$router.push({ path: `/channel/${this.channelId}` })
|
||||
},
|
||||
|
||||
toggleSave: function () {
|
||||
if (this.inFavoritesPlaylist) {
|
||||
this.removeFromPlaylist()
|
||||
} else {
|
||||
this.addToPlaylist()
|
||||
}
|
||||
},
|
||||
|
||||
handleSubscription: function () {
|
||||
if (this.channelId === '') {
|
||||
return
|
||||
|
@ -291,9 +331,52 @@ export default Vue.extend({
|
|||
shell.openExternal(url)
|
||||
},
|
||||
|
||||
addToPlaylist: function () {
|
||||
const videoData = {
|
||||
videoId: this.id,
|
||||
title: this.title,
|
||||
author: this.channelName,
|
||||
authorId: this.channelId,
|
||||
published: '',
|
||||
description: this.description,
|
||||
viewCount: this.viewCount,
|
||||
lengthSeconds: this.lengthSeconds,
|
||||
timeAdded: new Date().getTime(),
|
||||
isLive: false,
|
||||
paid: false,
|
||||
type: 'video'
|
||||
}
|
||||
|
||||
const payload = {
|
||||
playlistName: 'Favorites',
|
||||
videoData: videoData
|
||||
}
|
||||
|
||||
this.addVideo(payload)
|
||||
|
||||
this.showToast({
|
||||
message: this.$t('Video.Video has been saved')
|
||||
})
|
||||
},
|
||||
|
||||
removeFromPlaylist: function () {
|
||||
const payload = {
|
||||
playlistName: 'Favorites',
|
||||
videoId: this.id
|
||||
}
|
||||
|
||||
this.removeVideo(payload)
|
||||
|
||||
this.showToast({
|
||||
message: this.$t('Video.Video has been removed from your saved list')
|
||||
})
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'updateProfile'
|
||||
'updateProfile',
|
||||
'addVideo',
|
||||
'removeVideo'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -63,7 +63,15 @@
|
|||
</div>
|
||||
<div class="videoOptions">
|
||||
<ft-icon-button
|
||||
v-if="!hideRecommendedVideos"
|
||||
v-if="!isUpcoming"
|
||||
:title="$t('Video.Save Video')"
|
||||
icon="star"
|
||||
class="option"
|
||||
:theme="favoriteIconTheme"
|
||||
@click="toggleSave"
|
||||
/>
|
||||
<ft-icon-button
|
||||
v-if="theatrePossible"
|
||||
:title="$t('Toggle Theatre Mode')"
|
||||
class="theatreModeButton option"
|
||||
icon="expand-alt"
|
||||
|
|
|
@ -155,7 +155,7 @@ export default Vue.extend({
|
|||
comment.message.forEach((text) => {
|
||||
if (typeof (text.navigationEndpoint) !== 'undefined') {
|
||||
if (typeof (text.navigationEndpoint.watchEndpoint) !== 'undefined') {
|
||||
const htmlRef = `<router-link to="/watch/${text.navigationEndpoint.watchEndpoint.videoId}">${text.text}</router-link>`
|
||||
const htmlRef = `<a href="https://www.youtube.com/watch?v=${text.navigationEndpoint.watchEndpoint.videoId}">${text.text}</a>`
|
||||
comment.messageHtml = comment.messageHtml + htmlRef
|
||||
} else {
|
||||
comment.messageHtml = comment.messageHtml + text.text
|
||||
|
|
|
@ -6,6 +6,10 @@ import store from './store/index'
|
|||
// import 'material-design-icons/iconfont/material-icons.css'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { fas } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons/faGithub'
|
||||
import { faBitcoin } from '@fortawesome/free-brands-svg-icons/faBitcoin'
|
||||
import { faMonero } from '@fortawesome/free-brands-svg-icons/faMonero'
|
||||
import { faMastodon } from '@fortawesome/free-brands-svg-icons/faMastodon'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
import VueI18n from 'vue-i18n'
|
||||
import yaml from 'js-yaml'
|
||||
|
@ -17,13 +21,13 @@ Vue.config.devtools = isDev
|
|||
Vue.config.performance = isDev
|
||||
Vue.config.productionTip = isDev
|
||||
|
||||
library.add(fas)
|
||||
library.add(fas, faGithub, faBitcoin, faMonero, faMastodon)
|
||||
|
||||
Vue.component('FontAwesomeIcon', FontAwesomeIcon)
|
||||
Vue.use(VueI18n)
|
||||
|
||||
// List of locales approved for use
|
||||
const activeLocales = ['en-US', 'en_GB', 'ar', 'bg', 'cs', 'da', 'de-DE', 'el', 'es', 'es-MX', 'fi', 'fr-FR', 'he', 'hu', 'hr', 'id', 'it', 'ja', 'nl', 'pl', 'pt', 'pt-BR', 'pt-PT', 'ru', 'sk', 'sl', 'sv', 'tr', 'vi', 'zh-CN', 'zh-TW']
|
||||
const activeLocales = ['en-US', 'en_GB', 'ar', 'bg', 'cs', 'da', 'de-DE', 'el', 'es', 'es-MX', 'fi', 'fr-FR', 'gl', 'he', 'hu', 'hr', 'id', 'it', 'ja', 'nl', 'pl', 'pt', 'pt-BR', 'pt-PT', 'ru', 'sk', 'sl', 'sv', 'tr', 'vi', 'zh-CN', 'zh-TW']
|
||||
const messages = {}
|
||||
/* eslint-disable-next-line */
|
||||
const fileLocation = isDev ? 'static/locales/' : `${__dirname}/static/locales/`
|
||||
|
@ -32,7 +36,7 @@ const fileLocation = isDev ? 'static/locales/' : `${__dirname}/static/locales/`
|
|||
activeLocales.forEach((locale) => {
|
||||
try {
|
||||
// File location when running in dev
|
||||
const doc = yaml.safeLoad(fs.readFileSync(`${fileLocation}${locale}.yaml`))
|
||||
const doc = yaml.load(fs.readFileSync(`${fileLocation}${locale}.yaml`))
|
||||
messages[locale] = doc
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
|
|
@ -169,6 +169,8 @@ $thumbnail-overlay-opacity: 0.85
|
|||
|
||||
.description
|
||||
font-size: 14px
|
||||
max-height: 50px
|
||||
overflow-y: hidden
|
||||
@include low-contrast-when-watched(var(--secondary-text-color))
|
||||
|
||||
&.list
|
||||
|
|
|
@ -4,60 +4,206 @@ let dbLocation
|
|||
|
||||
if (window && window.process && window.process.type === 'renderer') {
|
||||
// Electron is being used
|
||||
let dbLocation = localStorage.getItem('dbLocation')
|
||||
// let dbLocation = localStorage.getItem('dbLocation')
|
||||
//
|
||||
// if (dbLocation === null) {
|
||||
// const electron = require('electron')
|
||||
// dbLocation = electron.remote.app.getPath('userData')
|
||||
// }
|
||||
//
|
||||
// dbLocation += '/playlists.db'
|
||||
|
||||
if (dbLocation === null) {
|
||||
const electron = require('electron')
|
||||
dbLocation = electron.remote.app.getPath('userData')
|
||||
}
|
||||
const electron = require('electron')
|
||||
dbLocation = electron.remote.app.getPath('userData')
|
||||
|
||||
dbLocation += '/playlists.db'
|
||||
dbLocation = dbLocation + '/playlists.db'
|
||||
} else {
|
||||
dbLocation = 'playlists.db'
|
||||
}
|
||||
|
||||
const subDb = new Datastore({
|
||||
const playlistDb = new Datastore({
|
||||
filename: dbLocation,
|
||||
autoload: true
|
||||
})
|
||||
|
||||
const state = {
|
||||
activePlaylistId: '',
|
||||
activePlaylistVideoList: [],
|
||||
watchedVideosWithinPlaylist: []
|
||||
playlists: [
|
||||
{
|
||||
playlistName: 'Favorites',
|
||||
protected: true,
|
||||
videos: []
|
||||
},
|
||||
{
|
||||
playlistName: 'WatchLater',
|
||||
protected: true,
|
||||
removeOnWatched: true,
|
||||
videos: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
addSubscription (state, payload) {
|
||||
state.subscriptions.push(payload)
|
||||
},
|
||||
setSubscriptions (state, payload) {
|
||||
state.subscriptions = payload
|
||||
}
|
||||
const getters = {
|
||||
getAllPlaylists: () => state.playlists,
|
||||
getFavorites: () => state.playlists[0],
|
||||
getPlaylist: (playlistId) => state.playlists.find(playlist => playlist._id === playlistId),
|
||||
getWatchLater: () => state.playlists[1]
|
||||
}
|
||||
|
||||
const actions = {
|
||||
addSubscriptions ({ commit }, payload) {
|
||||
subDb.insert(payload, (err, payload) => {
|
||||
if (!err) {
|
||||
commit('addSubscription', payload)
|
||||
addPlaylist ({ commit }, payload) {
|
||||
playlistDb.insert(payload, (err, payload) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('addPlaylist', payload)
|
||||
}
|
||||
})
|
||||
},
|
||||
getSubscriptions ({ commit }, payload) {
|
||||
subDb.find({}, (err, payload) => {
|
||||
if (!err) {
|
||||
commit('setSubscriptions', payload)
|
||||
addPlaylists ({ commit }, payload) {
|
||||
playlistDb.insert(payload, (err, payload) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('addPlaylists', payload)
|
||||
}
|
||||
})
|
||||
},
|
||||
removeSubscription ({ commit }, channelId) {
|
||||
subDb.remove({ channelId: channelId }, {}, () => {
|
||||
commit('setSubscriptions', this.state.subscriptions.filter(sub => sub.channelId !== channelId))
|
||||
addVideo ({ commit }, payload) {
|
||||
playlistDb.update({ playlistName: payload.playlistName }, { $push: { videos: payload.videoData } }, { upsert: true }, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('addVideo', payload)
|
||||
}
|
||||
})
|
||||
},
|
||||
addVideos ({ commit }, payload) {
|
||||
playlistDb.update({ _id: payload.playlistId }, { $push: { videos: { $each: payload.videosIds } } }, { upsert: true }, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('addVideos', payload)
|
||||
}
|
||||
})
|
||||
},
|
||||
grabAllPlaylists({ commit, dispatch }) {
|
||||
playlistDb.find({}, (err, payload) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
if (payload.length === 0) {
|
||||
commit('setAllPlaylists', state.playlists)
|
||||
dispatch('addPlaylists', payload)
|
||||
} else {
|
||||
commit('setAllPlaylists', payload)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
removeAllPlaylists ({ commit }) {
|
||||
playlistDb.remove({ protected: { $ne: true } }, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removeAllPlaylists')
|
||||
}
|
||||
})
|
||||
},
|
||||
removeAllVideos ({ commit }, playlistName) {
|
||||
playlistDb.update({ playlistName: playlistName }, { $set: { videos: [] } }, { upsert: true }, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removeAllVideos', playlistName)
|
||||
}
|
||||
})
|
||||
},
|
||||
removePlaylist ({ commit }, playlistId) {
|
||||
playlistDb.remove({ _id: playlistId, protected: { $ne: true } }, (err, playlistId) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removePlaylist', playlistId)
|
||||
}
|
||||
})
|
||||
},
|
||||
removePlaylists ({ commit }, playlistIds) {
|
||||
playlistDb.remove({ _id: { $in: playlistIds }, protected: { $ne: true } }, (err, playlistIds) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removePlaylists', playlistIds)
|
||||
}
|
||||
})
|
||||
},
|
||||
removeVideo ({ commit }, payload) {
|
||||
playlistDb.update({ playlistName: payload.playlistName }, { $pull: { videos: { videoId: payload.videoId } } }, { upsert: true }, (err, numRemoved) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removeVideo', payload)
|
||||
}
|
||||
})
|
||||
},
|
||||
removeVideos ({ commit }, payload) {
|
||||
playlistDb.update({ _id: payload.playlistName }, { $pull: { videos: { $in: payload.videoId } } }, { upsert: true }, err => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
} else {
|
||||
commit('removeVideos', payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
const getters = {}
|
||||
|
||||
const mutations = {
|
||||
addPlaylist (state, payload) {
|
||||
state.playlists.push(payload)
|
||||
},
|
||||
addPlaylists (state, payload) {
|
||||
state.playlists = state.playlists.concat(payload)
|
||||
},
|
||||
addVideo (state, payload) {
|
||||
const playlist = state.playlists.find(playlist => playlist.playlistName === payload.playlistName)
|
||||
if (playlist) {
|
||||
playlist.videos.push(payload.videoData)
|
||||
}
|
||||
},
|
||||
addVideos (state, payload) {
|
||||
const playlist = state.playlists.find(playlist => playlist._id === payload.playlistId)
|
||||
if (playlist) {
|
||||
playlist.videos = playlist.videos.concat(payload.playlistIds)
|
||||
}
|
||||
},
|
||||
removeAllPlaylists (state) {
|
||||
state.playlists = state.playlists.filter(playlist => playlist.protected !== true)
|
||||
},
|
||||
removeAllVideos (state, playlistName) {
|
||||
const playlist = state.playlists.find(playlist => playlist.playlistName === playlistName)
|
||||
if (playlist) {
|
||||
playlist.videos = []
|
||||
}
|
||||
},
|
||||
removeVideo (state, payload) {
|
||||
const playlist = state.playlists.findIndex(playlist => playlist.playlistName === payload.playlistName)
|
||||
if (playlist !== -1) {
|
||||
state.playlists[playlist].videos = state.playlists[playlist].videos.filter(video => video.videoId !== payload.videoId)
|
||||
}
|
||||
},
|
||||
removeVideos (state, payload) {
|
||||
const playlist = state.playlists.findIndex(playlist => playlist._id === payload.playlistId)
|
||||
if (playlist !== -1) {
|
||||
playlist.videos = playlist.videos.filter(video => payload.videoId.indexOf(video) === -1)
|
||||
}
|
||||
},
|
||||
removePlaylist (state, playlistId) {
|
||||
state.playlists = state.playlists.filter(playlist => playlist._id !== playlistId || playlist.protected)
|
||||
},
|
||||
setAllPlaylists (state, payload) {
|
||||
state.playlists = payload
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters,
|
||||
|
|
|
@ -57,8 +57,10 @@ const state = {
|
|||
defaultPlayback: 1,
|
||||
defaultVideoFormat: 'dash',
|
||||
defaultQuality: '720',
|
||||
useTor: false,
|
||||
proxy: 'SOCKS5://127.0.0.1:9050',
|
||||
useProxy: false,
|
||||
proxyProtocol: 'socks5',
|
||||
proxyHostname: '127.0.0.1',
|
||||
proxyPort: '9050',
|
||||
debugMode: false,
|
||||
disableSmoothScrolling: false,
|
||||
hideWatchedSubs: false,
|
||||
|
@ -71,7 +73,8 @@ const state = {
|
|||
hideRecommendedVideos: false,
|
||||
hideTrendingVideos: false,
|
||||
hidePopularVideos: false,
|
||||
hideLiveChat: false
|
||||
hideLiveChat: false,
|
||||
hideActiveSubscriptions: false
|
||||
}
|
||||
|
||||
const getters = {
|
||||
|
@ -159,6 +162,22 @@ const getters = {
|
|||
return state.proxyVideos
|
||||
},
|
||||
|
||||
getUseProxy: () => {
|
||||
return state.useProxy
|
||||
},
|
||||
|
||||
getProxyProtocol: () => {
|
||||
return state.proxyProtocol
|
||||
},
|
||||
|
||||
getProxyHostname: () => {
|
||||
return state.proxyHostname
|
||||
},
|
||||
|
||||
getProxyPort: () => {
|
||||
return state.proxyPort
|
||||
},
|
||||
|
||||
getDefaultTheatreMode: () => {
|
||||
return state.defaultTheatreMode
|
||||
},
|
||||
|
@ -224,6 +243,9 @@ const getters = {
|
|||
},
|
||||
getHideLiveChat: () => {
|
||||
return state.hideLiveChat
|
||||
},
|
||||
getHideActiveSubscriptions: () => {
|
||||
return state.hideActiveSubscriptions
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +333,18 @@ const actions = {
|
|||
case 'proxyVideos':
|
||||
commit('setProxyVideos', result.value)
|
||||
break
|
||||
case 'useProxy':
|
||||
commit('setUseProxy', result.value)
|
||||
break
|
||||
case 'proxyProtocol':
|
||||
commit('setProxyProtocol', result.value)
|
||||
break
|
||||
case 'proxyHostname':
|
||||
commit('setProxyHostname', result.value)
|
||||
break
|
||||
case 'proxyPort':
|
||||
commit('setProxyPort', result.value)
|
||||
break
|
||||
case 'defaultTheatreMode':
|
||||
commit('setDefaultTheatreMode', result.value)
|
||||
break
|
||||
|
@ -351,6 +385,9 @@ const actions = {
|
|||
case 'hideLiveChat':
|
||||
commit('setHideLiveChat', result.value)
|
||||
break
|
||||
case 'hideActiveSubscriptions':
|
||||
commit('setHideActiveSubscriptions', result.value)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -583,10 +620,34 @@ const actions = {
|
|||
})
|
||||
},
|
||||
|
||||
updateUseTor ({ commit }, useTor) {
|
||||
settingsDb.update({ _id: useTor }, { value: useTor }, { upsert: true }, (err, useTor) => {
|
||||
updateUseProxy ({ commit }, useProxy) {
|
||||
settingsDb.update({ _id: 'useProxy' }, { _id: 'useProxy', value: useProxy }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setUseTor', useTor)
|
||||
commit('setUseProxy', useProxy)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateProxyProtocol ({ commit }, proxyProtocol) {
|
||||
settingsDb.update({ _id: 'proxyProtocol' }, { _id: 'proxyProtocol', value: proxyProtocol }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setProxyProtocol', proxyProtocol)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateProxyHostname ({ commit }, proxyHostname) {
|
||||
settingsDb.update({ _id: 'proxyHostname' }, { _id: 'proxyHostname', value: proxyHostname }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setProxyHostname', proxyHostname)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateProxyPort ({ commit }, proxyPort) {
|
||||
settingsDb.update({ _id: 'proxyPort' }, { _id: 'proxyPort', value: proxyPort }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setProxyPort', proxyPort)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -655,6 +716,14 @@ const actions = {
|
|||
})
|
||||
},
|
||||
|
||||
updateHideActiveSubscriptions ({ commit }, hideActiveSubscriptions) {
|
||||
settingsDb.update({ _id: 'hideActiveSubscriptions' }, { _id: 'hideActiveSubscriptions', value: hideActiveSubscriptions }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setHideActiveSubscriptions', hideActiveSubscriptions)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateHideLiveChat ({ commit }, hideLiveChat) {
|
||||
settingsDb.update({ _id: 'hideLiveChat' }, { _id: 'hideLiveChat', value: hideLiveChat }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
|
@ -749,8 +818,17 @@ const mutations = {
|
|||
setDefaultTheatreMode (state, defaultTheatreMode) {
|
||||
state.defaultTheatreMode = defaultTheatreMode
|
||||
},
|
||||
setUseTor (state, useTor) {
|
||||
state.useTor = useTor
|
||||
setUseProxy (state, useProxy) {
|
||||
state.useProxy = useProxy
|
||||
},
|
||||
setProxyProtocol (state, proxyProtocol) {
|
||||
state.proxyProtocol = proxyProtocol
|
||||
},
|
||||
setProxyHostname (state, proxyHostname) {
|
||||
state.proxyHostname = proxyHostname
|
||||
},
|
||||
setProxyPort (state, proxyPort) {
|
||||
state.proxyPort = proxyPort
|
||||
},
|
||||
setDebugMode (state, debugMode) {
|
||||
state.debugMode = debugMode
|
||||
|
@ -796,6 +874,9 @@ const mutations = {
|
|||
},
|
||||
setHideLiveChat (state, hideLiveChat) {
|
||||
state.hideLiveChat = hideLiveChat
|
||||
},
|
||||
setHideActiveSubscriptions (state, hideActiveSubscriptions) {
|
||||
state.hideActiveSubscriptions = hideActiveSubscriptions
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -212,6 +212,12 @@ const actions = {
|
|||
return urlObject.pathname.slice(1)
|
||||
}
|
||||
},
|
||||
// youtube.com/embed
|
||||
function() {
|
||||
if (urlObject.pathname.match(/^\/embed\/[A-Za-z0-9_-]+$/)) {
|
||||
return urlObject.pathname.replace('/embed/', '')
|
||||
}
|
||||
},
|
||||
// cloudtube
|
||||
function() {
|
||||
if (urlObject.host.match(/^cadence\.(gq|moe)$/) && urlObject.pathname.match(/^\/cloudtube\/video\/[A-Za-z0-9_-]+$/)) {
|
||||
|
@ -223,6 +229,27 @@ const actions = {
|
|||
return extractors.reduce((a, c) => a || c(), null) || false
|
||||
},
|
||||
|
||||
getPlaylistIdFromUrl (_, url) {
|
||||
/** @type {URL} */
|
||||
let urlObject
|
||||
try {
|
||||
urlObject = new URL(url)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
|
||||
const extractors = [
|
||||
// anything with /playlist?list=
|
||||
function() {
|
||||
if (urlObject.pathname === '/playlist' && urlObject.searchParams.has('list')) {
|
||||
return urlObject.searchParams.get('list')
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
return extractors.reduce((a, c) => a || c(), null) || false
|
||||
},
|
||||
|
||||
padNumberWithLeadingZeros(_, payload) {
|
||||
let numberString = payload.number.toString()
|
||||
while (numberString.length < payload.length) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
--bg-color: #f1f1f1;
|
||||
--link-color: var(--accent-color);
|
||||
--link-visited-color: var(--accent-color-visited);
|
||||
--favorite-icon-color: #FFD600;
|
||||
--card-bg-color: #FFFFFF;
|
||||
--secondary-card-bg-color: #eeeeee;
|
||||
--scrollbar-color: #CCCCCC;
|
||||
|
@ -32,6 +33,7 @@
|
|||
--bg-color: #212121;
|
||||
--link-color: var(--accent-color);
|
||||
--link-visited-color: var(--accent-color-visited);
|
||||
--favorite-icon-color: #FFEA00;
|
||||
--card-bg-color: #303030;
|
||||
--secondary-card-bg-color: rgba(0, 0, 0, 0.75);
|
||||
--scrollbar-color: #414141;
|
||||
|
@ -55,6 +57,7 @@
|
|||
--bg-color: #000000;
|
||||
--link-color: var(--accent-color);
|
||||
--link-visited-color: var(--accent-color-visited);
|
||||
--favorite-icon-color: #FFEA00;
|
||||
--card-bg-color: #000000;
|
||||
--secondary-card-bg-color: rgba(0, 0, 0, 0.75);
|
||||
--scrollbar-color: #515151;
|
||||
|
|
|
@ -449,7 +449,6 @@ body.vjs-full-window {
|
|||
content: url(assets/img/open_fullwindow.svg);
|
||||
}
|
||||
|
||||
|
||||
.vjs-icon-fullwindow-exit, .video-js.vjs-fullwindow .vjs-fullwindow-control .vjs-icon-placeholder {
|
||||
font-family: VideoJS;
|
||||
font-weight: normal;
|
||||
|
@ -459,6 +458,30 @@ body.vjs-full-window {
|
|||
content: url(assets/img/close_fullwindow.svg);
|
||||
}
|
||||
|
||||
.vjs-icon-loop, .video-js .vjs-fullwindow-control .vjs-icon-placeholder {
|
||||
color: white !important;
|
||||
margin-top: 5px !important;
|
||||
padding-top: 5px !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vjs-icon-loop-active {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.vjs-icon-loop:before, .video-js.vjs-fullwindow .vjs-fullwindow-control .vjs-icon-placeholder:before {
|
||||
content: url(assets/img/loop.svg);
|
||||
/* filter: invert(1) drop-shadow(1px 0px 0px var(--primary-color)); */
|
||||
}
|
||||
|
||||
.loop-black:before {
|
||||
filter: brightness(0%);
|
||||
}
|
||||
|
||||
.loop-white:before {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
.vjs-full-window .video-js.vjs-fullscreen {
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
.card {
|
||||
width: 85%;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 60px;
|
||||
margin-bottom: 10px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Vue from 'vue'
|
||||
import FtCard from '../../components/ft-card/ft-card.vue'
|
||||
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
|
||||
import FtButton from '../../components/ft-button/ft-button.vue'
|
||||
|
||||
const { version } = require('../../../../package.json')
|
||||
|
||||
|
@ -8,13 +9,97 @@ export default Vue.extend({
|
|||
name: 'About',
|
||||
components: {
|
||||
'ft-card': FtCard,
|
||||
'ft-element-list': FtElementList
|
||||
'ft-element-list': FtElementList,
|
||||
'ft-button': FtButton
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
versionNumber: `v${version}`
|
||||
versionNumber: `v${version}`,
|
||||
chunks: [
|
||||
{
|
||||
icon: ['fab', 'github'],
|
||||
title: this.$t('About.Source code'),
|
||||
content: `<a href="https://github.com/FreeTubeApp/FreeTube">GitHub: FreeTubeApp/FreeTube</a><br>${this.$t('About.Licensed under the AGPLv3')} <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">${this.$t('About.View License')}</a>`
|
||||
},
|
||||
{
|
||||
icon: 'file-download',
|
||||
title: this.$t('About.Downloads / Changelog'),
|
||||
content: `<a href="https://github.com/FreeTubeApp/FreeTube/releases">${this.$t('About.GitHub releases')}</a>`
|
||||
},
|
||||
{
|
||||
icon: 'question-circle',
|
||||
title: this.$t('About.Help'),
|
||||
content: `<a href="https://github.com/FreeTubeApp/FreeTube/wiki">${this.$t('About.FreeTube Wiki')}</a> / <a href="https://github.com/FreeTubeApp/FreeTube/wiki/F.A.Q.">${this.$t('About.FAQ')}</a>`
|
||||
},
|
||||
{
|
||||
icon: 'exclamation-circle',
|
||||
title: this.$t('About.Report a problem'),
|
||||
content: `<a href="https://github.com/FreeTubeApp/FreeTube/issues">${this.$t('About.GitHub issues')}</a><br>${this.$t('About.Please check for duplicates before posting')}`
|
||||
},
|
||||
{
|
||||
icon: 'globe',
|
||||
title: this.$t('About.Website'),
|
||||
content: '<a href="https://freetubeapp.io/">https://freetubeapp.io/</a>'
|
||||
},
|
||||
{
|
||||
icon: 'newspaper',
|
||||
title: this.$t('About.Blog'),
|
||||
content: '<a href="https://freetube.writeas.com/">https://freetube.writeas.com/</a>'
|
||||
},
|
||||
{
|
||||
icon: 'envelope',
|
||||
title: this.$t('About.Email'),
|
||||
content: '<a href="mailto:FreeTubeApp@protonmail.com">FreeTubeApp@protonmail.com</a>'
|
||||
},
|
||||
{
|
||||
icon: ['fab', 'mastodon'],
|
||||
title: this.$t('About.Mastodon'),
|
||||
content: '<a href="https://mastodon.technology/@FreeTube">@FreeTube@mastodon.technology</a>'
|
||||
},
|
||||
{
|
||||
icon: 'comment-dots',
|
||||
title: this.$t('About.Chat on Matrix'),
|
||||
content: `<a href="https://matrix.to/#/#freetube:matrix.org?via=matrix.org&via=privacytools.io&via=tchncs.de">#freetube:matrix.org</a><br>${this.$t('About.Please read the')} <a href="https://github.com/FreeTubeApp/FreeTube/wiki/Matrix-Channel-Info-&-Rules">${this.$t('About.room rules')}</a>`
|
||||
},
|
||||
{
|
||||
icon: 'language',
|
||||
title: this.$t('About.Translate'),
|
||||
content: '<a href="https://hosted.weblate.org/engage/free-tube/">https://hosted.weblate.org/engage/free-tube/</a>'
|
||||
},
|
||||
{
|
||||
icon: 'users',
|
||||
title: this.$t('About.Credits'),
|
||||
content: `${this.$t('About.FreeTube is made possible by')} <a href="https://github.com/FreeTubeApp/FreeTube/wiki/Credits">${this.$t('About.these people and projects')}</a>`
|
||||
},
|
||||
{
|
||||
icon: 'heart',
|
||||
title: `${this.$t('About.Donate')} - Liberapay`,
|
||||
content: '<a href="https://liberapay.com/FreeTube">https://liberapay.com/FreeTube</a>'
|
||||
},
|
||||
{
|
||||
icon: ['fab', 'bitcoin'],
|
||||
title: `${this.$t('About.Donate')} - BTC`,
|
||||
content: '<a href="bitcoin:1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS">1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS</a>'
|
||||
},
|
||||
{
|
||||
icon: ['fab', 'monero'],
|
||||
title: `${this.$t('About.Donate')} - XMR`,
|
||||
content: '<a href="monero:48WyAPdjwc6VokeXACxSZCFeKEXBiYPV6GjfvBsfg4CrUJ95LLCQSfpM9pvNKy5GE5H4hNaw99P8RZyzmaU9kb1pD7kzhCB">48WyAPdjwc6VokeXACxSZCFeKEXBiYPV6GjfvBsfg4CrUJ95LLCQSfpM9pvNKy5GE5H4hNaw99P8RZyzmaU9kb1pD7kzhCB</a>'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
computed: {
|
||||
usingElectron: function () {
|
||||
return this.$store.getters.getUsingElectron
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openUrl: function (url) {
|
||||
if (this.usingElectron) {
|
||||
const shell = require('electron').shell
|
||||
shell.openExternal(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
.card
|
||||
width: 85%
|
||||
margin: 0 auto
|
||||
margin-bottom: 60px
|
||||
|
||||
@media only screen and (max-width: 680px)
|
||||
width: 90%
|
||||
|
||||
.brand
|
||||
text-align: center
|
||||
|
||||
.logo
|
||||
width: 500px
|
||||
max-width: 100%
|
||||
|
||||
.version
|
||||
font-size: 2em
|
||||
|
||||
.about-chunks
|
||||
max-width: 860px
|
||||
margin: 80px auto
|
||||
display: grid
|
||||
grid-template-columns: 1fr 1fr
|
||||
grid-gap: 16px
|
||||
|
||||
@media only screen and (max-width: 650px)
|
||||
grid-template-columns: 1fr
|
||||
|
||||
.chunk
|
||||
background-color: var(--bg-color)
|
||||
margin: 0
|
||||
padding: 18px
|
||||
border-radius: 8px
|
||||
display: grid
|
||||
grid-template: "icon title" auto "icon content" 1fr / auto 1fr
|
||||
justify-content: start
|
||||
align-items: start
|
||||
grid-gap: 6px 14px
|
||||
word-break: break-word
|
||||
box-shadow: 0px 1px 4px -1px rgba(0, 0, 0, 0.5)
|
||||
|
||||
@each $area in icon title content
|
||||
.#{$area}
|
||||
grid-area: $area
|
||||
|
||||
.icon
|
||||
font-size: 24px
|
||||
|
||||
.title
|
||||
margin: 0
|
|
@ -1,64 +1,40 @@
|
|||
<template>
|
||||
<div>
|
||||
<ft-card class="card center">
|
||||
<h3 class="leftAlign">
|
||||
About
|
||||
</h3>
|
||||
<img
|
||||
src="_icons/logoColor.png"
|
||||
class="logo"
|
||||
>
|
||||
<ft-card class="card">
|
||||
<h1>
|
||||
{{ versionNumber }} Beta
|
||||
{{ $t("About.About") }}
|
||||
</h1>
|
||||
<h3>
|
||||
<font-awesome-icon
|
||||
icon="envelope"
|
||||
/>
|
||||
FreeTubeApp@protonmail.com
|
||||
</h3>
|
||||
<h2>
|
||||
This software is FOSS and released under the
|
||||
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html">GNU Affero General Public License v3.0</a>.
|
||||
</h2>
|
||||
<p>
|
||||
Found a bug? Want to suggest a feature? Want to help out? Check out our
|
||||
<a href="https://github.com/FreeTubeApp/FreeTube">GitHub</a>
|
||||
page. Pull requests are welcome.
|
||||
</p>
|
||||
<p>
|
||||
Thank you very much to the
|
||||
<a href="https://github.com/FreeTubeApp/FreeTube/wiki/Credits">People and Projects</a>
|
||||
that make FreeTube possible!
|
||||
</p>
|
||||
<p>
|
||||
Want to chat? Join our
|
||||
<a href="https://app.element.io/#/group/+freetube:matrix.org">Element / Matrix Server</a>
|
||||
. Please check the
|
||||
<a href="https://github.com/FreeTubeApp/FreeTube/wiki/Matrix-Server-Info-&-Rules">rules</a>
|
||||
before joining.
|
||||
</p>
|
||||
<p>
|
||||
Looking for help? Check out our
|
||||
<a href="https://github.com/FreeTubeApp/FreeTube/wiki">Wiki</a>
|
||||
page.
|
||||
</p>
|
||||
<p>
|
||||
Check out our
|
||||
<a href="https://addons.mozilla.org/en-US/firefox/addon/freetube-redirect/">Firefox</a>
|
||||
extension!
|
||||
</p>
|
||||
<p>
|
||||
If you enjoy using FreeTube, consider donating via
|
||||
<a href="https://liberapay.com/FreeTube">Liberapay</a>
|
||||
or through our Bitcoin address.
|
||||
</p>
|
||||
<p>
|
||||
BTC: 1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS
|
||||
</p>
|
||||
<section class="brand">
|
||||
<img
|
||||
src="_icons/logoColor.png"
|
||||
class="logo"
|
||||
>
|
||||
<div class="version">
|
||||
{{ versionNumber }} {{ $t("About.Beta") }}
|
||||
</div>
|
||||
</section>
|
||||
<section class="about-chunks">
|
||||
<figure
|
||||
v-for="chunk in chunks"
|
||||
:key="chunk.title"
|
||||
class="chunk"
|
||||
>
|
||||
<font-awesome-icon
|
||||
class="icon"
|
||||
:icon="chunk.icon"
|
||||
/>
|
||||
<h3 class="title">
|
||||
{{ chunk.title }}
|
||||
</h3>
|
||||
<div
|
||||
class="content"
|
||||
v-html="chunk.content"
|
||||
/>
|
||||
</figure>
|
||||
</section>
|
||||
</ft-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./About.js" />
|
||||
<style scoped src="./About.css" />
|
||||
<style scoped src="./About.sass" lang="sass" />
|
||||
|
|
|
@ -410,7 +410,10 @@ export default Vue.extend({
|
|||
getPlaylistsLocal: function () {
|
||||
ytch.getChannelPlaylistInfo(this.id, this.playlistSortBy).then((response) => {
|
||||
console.log(response)
|
||||
this.latestPlaylists = response.items
|
||||
this.latestPlaylists = response.items.map((item) => {
|
||||
item.proxyThumbnail = false
|
||||
return item
|
||||
})
|
||||
this.playlistContinuationString = response.continuation
|
||||
this.isElementListLoading = false
|
||||
}).catch((err) => {
|
||||
|
|
|
@ -154,7 +154,7 @@ export default Vue.extend({
|
|||
published: publishDate,
|
||||
publishedText: publishDate,
|
||||
lengthSeconds: videoDuration,
|
||||
liveNow: video.live,
|
||||
liveNow: video.isLive,
|
||||
paid: false,
|
||||
premium: false,
|
||||
isUpcoming: false,
|
||||
|
@ -179,7 +179,7 @@ export default Vue.extend({
|
|||
query: payload.query,
|
||||
data: this.shownResults,
|
||||
searchSettings: this.searchSettings,
|
||||
nextPageRef: result.nextpageRef
|
||||
nextPageRef: result.continuation
|
||||
}
|
||||
|
||||
this.$store.commit('addToSessionSearchHistory', historyPayload)
|
||||
|
@ -200,7 +200,6 @@ export default Vue.extend({
|
|||
this.performSearchInvidious(payload)
|
||||
} else {
|
||||
this.isLoading = false
|
||||
// TODO: Show toast with error message
|
||||
}
|
||||
})
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ import SubscriptionSettings from '../../components/subscription-settings/subscri
|
|||
import PrivacySettings from '../../components/privacy-settings/privacy-settings.vue'
|
||||
import DataSettings from '../../components/data-settings/data-settings.vue'
|
||||
import DistractionSettings from '../../components/distraction-settings/distraction-settings.vue'
|
||||
import ProxySettings from '../../components/proxy-settings/proxy-settings.vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Settings',
|
||||
|
@ -20,6 +21,7 @@ export default Vue.extend({
|
|||
'subscription-settings': SubscriptionSettings,
|
||||
'privacy-settings': PrivacySettings,
|
||||
'data-settings': DataSettings,
|
||||
'distraction-settings': DistractionSettings
|
||||
'distraction-settings': DistractionSettings,
|
||||
'proxy-settings': ProxySettings
|
||||
}
|
||||
})
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<distraction-settings />
|
||||
<privacy-settings />
|
||||
<data-settings />
|
||||
<proxy-settings />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import Vue from 'vue'
|
||||
import FtCard from '../../components/ft-card/ft-card.vue'
|
||||
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
|
||||
import FtTooltip from '../../components/ft-tooltip/ft-tooltip.vue'
|
||||
import FtLoader from '../../components/ft-loader/ft-loader.vue'
|
||||
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
|
||||
|
||||
export default Vue.extend({
|
||||
|
@ -8,8 +10,48 @@ export default Vue.extend({
|
|||
components: {
|
||||
'ft-card': FtCard,
|
||||
'ft-flex-box': FtFlexBox,
|
||||
'ft-tooltip': FtTooltip,
|
||||
'ft-loader': FtLoader,
|
||||
'ft-element-list': FtElementList
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
isLoading: false,
|
||||
dataLimit: 100
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
favoritesPlaylist: function () {
|
||||
return this.$store.getters.getFavorites
|
||||
},
|
||||
|
||||
activeData: function () {
|
||||
if (this.favoritesPlaylist.videos.length < this.dataLimit) {
|
||||
return this.favoritesPlaylist.videos
|
||||
} else {
|
||||
return this.favoritesPlaylist.videos.slice(0, this.dataLimit)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeData() {
|
||||
this.isLoading = true
|
||||
setTimeout(() => {
|
||||
this.isLoading = false
|
||||
}, 100)
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
const limit = sessionStorage.getItem('favoritesLimit')
|
||||
|
||||
if (limit !== null) {
|
||||
this.dataLimit = limit
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
increaseLimit: function () {
|
||||
this.dataLimit += 100
|
||||
sessionStorage.setItem('favoritesLimit', this.dataLimit)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,12 +1,42 @@
|
|||
<template>
|
||||
<div>
|
||||
<ft-card class="card">
|
||||
<h3>{{ $t("User Playlists.Your Playlists") }}</h3>
|
||||
<ft-flex-box>
|
||||
<ft-loader
|
||||
v-if="isLoading"
|
||||
:fullscreen="true"
|
||||
/>
|
||||
<ft-card
|
||||
v-else
|
||||
class="card"
|
||||
>
|
||||
<h3>
|
||||
{{ $t("User Playlists.Your Playlists") }}
|
||||
<ft-tooltip
|
||||
class="selectTooltip"
|
||||
position="bottom"
|
||||
:tooltip="$t('User Playlists.Playlist Message')"
|
||||
/>
|
||||
</h3>
|
||||
<ft-flex-box
|
||||
v-if="activeData.length === 0"
|
||||
>
|
||||
<p class="message">
|
||||
{{ $t("This part of the app is not ready yet. Come back later when progress has been made.") }}
|
||||
{{ $t("User Playlists['Your saved videos are empty. Click on the save button on the corner of a video to have it listed here']") }}
|
||||
</p>
|
||||
</ft-flex-box>
|
||||
<ft-element-list
|
||||
v-else
|
||||
:data="activeData"
|
||||
/>
|
||||
<ft-flex-box
|
||||
v-if="activeData.length < favoritesPlaylist.videos.length"
|
||||
>
|
||||
<ft-button
|
||||
label="Load More"
|
||||
background-color="var(--primary-color)"
|
||||
text-color="var(--text-with-main-color)"
|
||||
@click="increaseLimit"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
</ft-card>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -119,6 +119,12 @@ export default Vue.extend({
|
|||
playNextVideo: function () {
|
||||
return this.$store.getters.getPlayNextVideo
|
||||
},
|
||||
hideRecommendedVideos: function () {
|
||||
return this.$store.getters.getHideRecommendedVideos
|
||||
},
|
||||
hideLiveChat: function () {
|
||||
return this.$store.getters.getHideLiveChat
|
||||
},
|
||||
|
||||
youtubeNoCookieEmbeddedFrame: function () {
|
||||
return `<iframe width='560' height='315' src='https://www.youtube-nocookie.com/embed/${this.videoId}?rel=0' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>`
|
||||
|
@ -128,6 +134,9 @@ export default Vue.extend({
|
|||
},
|
||||
hideVideoLikesAndDislikes: function () {
|
||||
return this.$store.getters.getHideVideoLikesAndDislikes
|
||||
},
|
||||
theatrePossible: function() {
|
||||
return !this.hideRecommendedVideos || (!this.hideLiveChat && this.isLive) || this.watchingPlaylist
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -197,7 +206,7 @@ export default Vue.extend({
|
|||
console.log(result)
|
||||
|
||||
const playabilityStatus = result.player_response.playabilityStatus
|
||||
if (playabilityStatus.status !== 'OK') {
|
||||
if (playabilityStatus.status === 'UNPLAYABLE') {
|
||||
const errorScreen = playabilityStatus.errorScreen.playerErrorMessageRenderer
|
||||
const reason = errorScreen.reason.simpleText
|
||||
let subReason
|
||||
|
@ -228,7 +237,9 @@ export default Vue.extend({
|
|||
this.channelId = result.player_response.videoDetails.channelId
|
||||
this.channelName = result.videoDetails.author.name
|
||||
console.log(result)
|
||||
this.channelThumbnail = result.videoDetails.author.thumbnails[0].url
|
||||
if (result.videoDetails.author.thumbnails.length > 0) {
|
||||
this.channelThumbnail = result.videoDetails.author.thumbnails[0].url
|
||||
}
|
||||
} else {
|
||||
this.channelId = result.player_response.videoDetails.channelId
|
||||
this.channelName = result.player_response.videoDetails.author
|
||||
|
@ -248,7 +259,7 @@ export default Vue.extend({
|
|||
this.thumbnail = `https://i.ytimg.com/vi/${this.videoId}/maxres3.jpg`
|
||||
break
|
||||
default:
|
||||
this.thumbnail = result.videoDetails.thumbnail.thumbnails[result.videoDetails.thumbnail.thumbnails.length - 1].url
|
||||
this.thumbnail = result.videoDetails.thumbnails[result.videoDetails.thumbnails.length - 1].url
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -264,8 +275,8 @@ export default Vue.extend({
|
|||
this.videoLikeCount = null
|
||||
this.videoDislikeCount = null
|
||||
} else {
|
||||
this.videoLikeCount = result.videoDetails.likes
|
||||
this.videoDislikeCount = result.videoDetails.dislikes
|
||||
this.videoLikeCount = isNaN(result.videoDetails.likes) ? 0 : result.videoDetails.likes
|
||||
this.videoDislikeCount = isNaN(result.videoDetails.dislikes) ? 0 : result.videoDetails.dislikes
|
||||
}
|
||||
this.isLive = result.player_response.videoDetails.isLive
|
||||
this.isLiveContent = result.player_response.videoDetails.isLiveContent
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
@media only screen and (max-width: 900px)
|
||||
+single-column-template
|
||||
|
||||
&.isLoading
|
||||
&.isLoading, &.noSidebar
|
||||
+single-column-template
|
||||
|
||||
.videoArea
|
||||
|
@ -73,6 +73,9 @@
|
|||
@media only screen and (min-width: 901px)
|
||||
min-width: 380px
|
||||
|
||||
@at-root .noSidebar#{&}
|
||||
grid-area: auto
|
||||
|
||||
.watchVideoPlaylist, .watchVideoSidebar, .theatrePlaylist
|
||||
margin: 0 8px 16px
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
class="videoLayout"
|
||||
:class="{
|
||||
isLoading,
|
||||
useTheatreMode
|
||||
useTheatreMode,
|
||||
noSidebar: !theatrePossible
|
||||
}"
|
||||
>
|
||||
<ft-loader
|
||||
|
@ -78,6 +79,9 @@
|
|||
:is-live="isLive"
|
||||
:is-upcoming="isUpcoming"
|
||||
:download-links="downloadLinks"
|
||||
:watching-playlist="watchingPlaylist"
|
||||
:theatre-possible="theatrePossible"
|
||||
:length-seconds="videoLengthSeconds"
|
||||
class="watchVideo"
|
||||
:class="{ theatreWatchVideo: useTheatreMode }"
|
||||
@theatre-mode="toggleTheatreMode"
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
{"id":328,"name":"غيانا","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"هايتي","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"هندوراس","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"هونغ كونغ","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"المجر","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"آيسلندا","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"الهند","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"Гвиана","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Хаити","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Хондурас","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Хонг Конг","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Унгария","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"Исландия","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"Индия","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hongkong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":152,"name":"Chile","alpha2":"cl","alpha3":"chl"},
|
||||
{"id":191,"name":"Chorvatsko","alpha2":"hr","alpha3":"hrv"},
|
||||
{"id":356,"name":"Indie","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":112,"name":"Hviderusland","alpha2":"by","alpha3":"blr"},
|
||||
{"id":356,"name":"Indien","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesien","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hongkong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":356,"name":"Indien","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesien","alpha2":"id","alpha3":"idn"},
|
||||
{"id":368,"name":"Irak","alpha2":"iq","alpha3":"irq"},
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
{"id":724,"name":"Hispaania","alpha2":"es","alpha3":"esp"},
|
||||
{"id":528,"name":"Holland","alpha2":"nl","alpha3":"nld"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":191,"name":"Horvaatia","alpha2":"hr","alpha3":"hrv"},
|
||||
{"id":372,"name":"Iirimaa","alpha2":"ie","alpha3":"irl"},
|
||||
{"id":376,"name":"Iisrael","alpha2":"il","alpha3":"isr"},
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
{"id":512,"name":"Ομάν","alpha2":"om","alpha3":"omn"},
|
||||
{"id":583,"name":"Ομόσπονδες Πολιτείες της Μικρονησίας","alpha2":"fm","alpha3":"fsm"},
|
||||
{"id":340,"name":"Ονδούρα","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Χονγκ Κονγκ","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Ουγγαρία","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":800,"name":"Ουγκάντα","alpha2":"ug","alpha3":"uga"},
|
||||
{"id":860,"name":"Ουζμπεκιστάν","alpha2":"uz","alpha3":"uzb"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungary","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"Iceland","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungary","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"Iceland","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haití","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungría","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haití","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungría","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haití","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungría","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
{"id":728,"name":"Hego Sudan","alpha2":"ss","alpha3":"ssd"},
|
||||
{"id":528,"name":"Herbehereak","alpha2":"nl","alpha3":"nld"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungaria","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
{"id":356,"name":"Intia","alpha2":"in","alpha3":"ind"},
|
||||
{"id":368,"name":"Irak","alpha2":"iq","alpha3":"irq"},
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haïti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hongrie","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":356,"name":"Inde","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonésie","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":528,"name":"Hollandia","alpha2":"nl","alpha3":"nld"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":191,"name":"Horvátország","alpha2":"hr","alpha3":"hrv"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonézia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
{"id":364,"name":"Iran","alpha2":"ir","alpha3":"irn"},
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
{"id":68,"name":"ボリビア多民族国","alpha2":"bo","alpha3":"bol"},
|
||||
{"id":620,"name":"ポルトガル","alpha2":"pt","alpha3":"prt"},
|
||||
{"id":340,"name":"ホンジュラス","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"香港","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":584,"name":"マーシャル諸島","alpha2":"mh","alpha3":"mhl"},
|
||||
{"id":450,"name":"マダガスカル","alpha2":"mg","alpha3":"mdg"},
|
||||
{"id":454,"name":"マラウイ","alpha2":"mw","alpha3":"mwi"},
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
{"id":36,"name":"오스트레일리아","alpha2":"au","alpha3":"aus"},
|
||||
{"id":40,"name":"오스트리아","alpha2":"at","alpha3":"aut"},
|
||||
{"id":340,"name":"온두라스","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"홍콩","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":400,"name":"요르단","alpha2":"jo","alpha3":"jor"},
|
||||
{"id":800,"name":"우간다","alpha2":"ug","alpha3":"uga"},
|
||||
{"id":858,"name":"우루과이","alpha2":"uy","alpha3":"ury"},
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
{"id":328,"name":"Gajana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haitis","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Hondūras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Honkongas","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Vengrija","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"Islandija","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"Indija","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":300,"name":"Hellas","alpha2":"gr","alpha3":"grc"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":112,"name":"Hviterussland","alpha2":"by","alpha3":"blr"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonesia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haïti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hongarije","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":372,"name":"Ierland","alpha2":"ie","alpha3":"irl"},
|
||||
{"id":352,"name":"IJsland","alpha2":"is","alpha3":"isl"},
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
{"id":724,"name":"Hiszpania","alpha2":"es","alpha3":"esp"},
|
||||
{"id":528,"name":"Holandia","alpha2":"nl","alpha3":"nld"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hongkong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":356,"name":"Indie","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonezja","alpha2":"id","alpha3":"idn"},
|
||||
{"id":368,"name":"Irak","alpha2":"iq","alpha3":"irq"},
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
{"id":226,"name":"Guiné Equatorial","alpha2":"gq","alpha3":"gnq"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungria","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":887,"name":"Iêmen","alpha2":"ye","alpha3":"yem"},
|
||||
{"id":356,"name":"Índia","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
{"id":226,"name":"Guiné Equatorial","alpha2":"gq","alpha3":"gnq"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungria","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":887,"name":"Iêmen","alpha2":"ye","alpha3":"yem"},
|
||||
{"id":356,"name":"Índia","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
{"id":226,"name":"Guiné Equatorial","alpha2":"gq","alpha3":"gnq"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Hungria","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":887,"name":"Iêmen","alpha2":"ye","alpha3":"yem"},
|
||||
{"id":356,"name":"Índia","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"Ungaria","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"Islanda","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
{"id":624,"name":"Гвинея-Бисау","alpha2":"gw","alpha3":"gnb"},
|
||||
{"id":276,"name":"Германия","alpha2":"de","alpha3":"deu"},
|
||||
{"id":340,"name":"Гондурас","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Гонконг","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":308,"name":"Гренада","alpha2":"gd","alpha3":"grd"},
|
||||
{"id":300,"name":"Греция","alpha2":"gr","alpha3":"grc"},
|
||||
{"id":268,"name":"Грузия","alpha2":"ge","alpha3":"geo"},
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":528,"name":"Holandsko","alpha2":"nl","alpha3":"nld"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hongkong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":191,"name":"Chorvátsko","alpha2":"hr","alpha3":"hrv"},
|
||||
{"id":356,"name":"India","alpha2":"in","alpha3":"ind"},
|
||||
{"id":360,"name":"Indonézia","alpha2":"id","alpha3":"idn"},
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
{"id":624,"name":"Guinea-Bissau","alpha2":"gw","alpha3":"gnb"},
|
||||
{"id":328,"name":"Guyana","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":340,"name":"Honduras","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Hong Kong","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":191,"name":"Kroatien","alpha2":"hr","alpha3":"hrv"},
|
||||
{"id":332,"name":"Haiti","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":348,"name":"Ungern","alpha2":"hu","alpha3":"hun"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"กายอานา","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"เฮติ","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"ฮอนดูรัส","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"ฮ่องกง","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"ฮังการี","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"ไอซ์แลนด์","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"อินเดีย","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
{"id":324,"name":"Гвінея","alpha2":"gn","alpha3":"gin"},
|
||||
{"id":624,"name":"Гвінея-Бісау","alpha2":"gw","alpha3":"gnb"},
|
||||
{"id":340,"name":"Гондурас","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"Гонконг","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":308,"name":"Гренада","alpha2":"gd","alpha3":"grd"},
|
||||
{"id":300,"name":"Греція","alpha2":"gr","alpha3":"grc"},
|
||||
{"id":268,"name":"Грузія","alpha2":"ge","alpha3":"geo"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"蓋亞那","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"海地","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"宏都拉斯","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"香港","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"匈牙利","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"冰島","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"印度","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{"id":328,"name":"圭亚那","alpha2":"gy","alpha3":"guy"},
|
||||
{"id":332,"name":"海地","alpha2":"ht","alpha3":"hti"},
|
||||
{"id":340,"name":"洪都拉斯","alpha2":"hn","alpha3":"hnd"},
|
||||
{"id":344,"name":"香港","alpha2":"hk","alpha3":"hkg"},
|
||||
{"id":348,"name":"匈牙利","alpha2":"hu","alpha3":"hun"},
|
||||
{"id":352,"name":"冰岛","alpha2":"is","alpha3":"isl"},
|
||||
{"id":356,"name":"印度","alpha2":"in","alpha3":"ind"},
|
||||
|
|
|
@ -561,12 +561,22 @@ Version $ is now available! Click for more details: الإصدار $ متاح
|
|||
على المزيد من التفاصيل
|
||||
Tooltips:
|
||||
General Settings:
|
||||
Thumbnail Preference: كلّ الصّور المصغّرة في FreeTube سيتمّ استبدالها بإيطار من
|
||||
Thumbnail Preference: كلّ الصّور المصغّرة في FreeTube سيتمّ استبدالها بإطار من
|
||||
الفيديو بدل من الصّورة المصغّرة الافتراضيّة
|
||||
Preferred API Backend: اختر الواجهة الخلفية التي يستخدمها FreeTube لجلب البيانات.
|
||||
الAPI المحلي هو مستخرج محلي. الAPI التابع لInvidious يتطلب التواصل مع خادم شبكة
|
||||
Invidious
|
||||
Invidious Instance: واجهة انفيديوس البرمجية المستخدمة من قبل فريتيوب. امسح الواجهة
|
||||
البرمجية الحالية للاختيار من قائمة الواجهات العلنية
|
||||
Preferred API Backend: اختر الواجهة الخلفية التي يستخدمها FreeTube لجلب البيانات
|
||||
. الAPI المحلي هو مستخرج محلي . الAPI التابع لInvidious يتطلب التواصل مع خادم
|
||||
شبكة Invidious .
|
||||
Invidious Instance: واجهة Invidious البرمجية المستخدمة من قبل FreeTube. امسح الواجهة
|
||||
البرمجية الحالية للاختيار من قائمة الواجهات
|
||||
Fallback to Non-Preferred Backend on Failure: عند تواجد مشكلة مع الواجهة البرمجية
|
||||
المفضلة لك، سوف يقوم فريتيوب باستخدام الواجهات الأخرى عند تفعيل هذا الخيار
|
||||
Region for Trending: يمكّنك اختيار الدولة من عرض الفيديوهات الشائعة التابعة للدولة
|
||||
التي تفضل . ليست كل البلدان المعروضة في هذه القائمة مدعومة من قبل يوتيوب
|
||||
Player Settings:
|
||||
Proxy Videos Through Invidious: سيتم الاتصال ب Invidious لتقديم مقاطع الفيديو
|
||||
بدلاً من إجراء اتصال مباشر مع يوتيوب. يلغي تفضيل الواجهة البرمجية
|
||||
Force Local Backend for Legacy Formats: تعمل فقط عندما تكون واجهة Invidious البرمجية
|
||||
هي الاختيار الافتراضي . عند تفعيل هذا الخيار ، ستعمل الواجهة البرمجية المحلية
|
||||
باستخدام التنسيقات القديمة التي تم إرجاعها من قبلها بدلاً من أن تستخدم الصيغ
|
||||
التي تم إرجاعها من قبل Invidious . يساعد هذا الخيار عندما لا تعمل الفيديوهات
|
||||
التي تم إرجاعها من قبل Invidious بسبب قيود البلد
|
||||
|
|
|
@ -0,0 +1,522 @@
|
|||
# Put the name of your locale in the same language
|
||||
Locale Name: ''
|
||||
FreeTube: 'ফ্রিটিউব'
|
||||
# Currently on Subscriptions, Playlists, and History
|
||||
'This part of the app is not ready yet. Come back later when progress has been made.': >
|
||||
|
||||
# Webkit Menu Bar
|
||||
File: 'ফাইল'
|
||||
Quit: 'প্রস্থান'
|
||||
Edit: 'সম্পাদনা'
|
||||
Undo: 'পূর্বাবস্থায় ফিরো'
|
||||
Redo: 'আবার করো'
|
||||
Cut: 'কাটো'
|
||||
Copy: 'অনুলিপি'
|
||||
Paste: 'লেপন'
|
||||
Delete: 'মুছো'
|
||||
Select all: ''
|
||||
Reload: 'পুনরায় লোড করো'
|
||||
Force Reload: ''
|
||||
Toggle Developer Tools: ''
|
||||
Actual size: ''
|
||||
Zoom in: ''
|
||||
Zoom out: ''
|
||||
Toggle fullscreen: ''
|
||||
Window: ''
|
||||
Minimize: ''
|
||||
Close: ''
|
||||
Back: ''
|
||||
Forward: ''
|
||||
|
||||
Version $ is now available! Click for more details: ''
|
||||
Download From Site: ''
|
||||
A new blog is now available, $. Click to view more: ''
|
||||
|
||||
# Search Bar
|
||||
Search / Go to URL: ''
|
||||
# In Filter Button
|
||||
Search Filters:
|
||||
Search Filters: ''
|
||||
Sort By:
|
||||
Sort By: ''
|
||||
Most Relevant: ''
|
||||
Rating: ''
|
||||
Upload Date: ''
|
||||
View Count: ''
|
||||
Time:
|
||||
Time: ''
|
||||
Any Time: ''
|
||||
Last Hour: ''
|
||||
Today: ''
|
||||
This Week: ''
|
||||
This Month: ''
|
||||
This Year: ''
|
||||
Type:
|
||||
Type: ''
|
||||
All Types: ''
|
||||
Videos: ''
|
||||
Channels: ''
|
||||
#& Playlists
|
||||
Duration:
|
||||
Duration: 'সময়কাল'
|
||||
All Durations: ''
|
||||
Short (< 4 minutes): ''
|
||||
Long (> 20 minutes): ''
|
||||
# On Search Page
|
||||
Search Results: ''
|
||||
Fetching results. Please wait: ''
|
||||
Fetch more results: ''
|
||||
# Sidebar
|
||||
Subscriptions:
|
||||
# On Subscriptions Page
|
||||
Subscriptions: ''
|
||||
Latest Subscriptions: ''
|
||||
This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: ''
|
||||
'Your Subscription list is currently empty. Start adding subscriptions to see them here.': ''
|
||||
'Getting Subscriptions. Please wait.': ''
|
||||
Refresh Subscriptions: ''
|
||||
Load More Videos: ''
|
||||
Trending: ''
|
||||
Most Popular: ''
|
||||
Playlists: ''
|
||||
User Playlists:
|
||||
Your Playlists: ''
|
||||
Playlist Message: ''
|
||||
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: ''
|
||||
History:
|
||||
# On History Page
|
||||
History: ''
|
||||
Watch History: ''
|
||||
Your history list is currently empty.: ''
|
||||
Settings:
|
||||
# On Settings Page
|
||||
Settings: ''
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: ''
|
||||
General Settings:
|
||||
General Settings: ''
|
||||
Check for Updates: ''
|
||||
Check for Latest Blog Posts: ''
|
||||
Fallback to Non-Preferred Backend on Failure: ''
|
||||
Enable Search Suggestions: ''
|
||||
Default Landing Page: ''
|
||||
Locale Preference: ''
|
||||
Preferred API Backend:
|
||||
Preferred API Backend: ''
|
||||
Local API: ''
|
||||
Invidious API: ''
|
||||
Video View Type:
|
||||
Video View Type: ''
|
||||
Grid: ''
|
||||
List: ''
|
||||
Thumbnail Preference:
|
||||
Thumbnail Preference: ''
|
||||
Default: ''
|
||||
Beginning: ''
|
||||
Middle: ''
|
||||
End: ''
|
||||
'Invidious Instance (Default is https://invidious.snopyta.org)': ''
|
||||
Region for Trending: ''
|
||||
#! List countries
|
||||
Theme Settings:
|
||||
Theme Settings: ''
|
||||
Match Top Bar with Main Color: ''
|
||||
Expand Side Bar by Default: ''
|
||||
Disable Smooth Scrolling: ''
|
||||
UI Scale: ''
|
||||
Base Theme:
|
||||
Base Theme: ''
|
||||
Black: ''
|
||||
Dark: ''
|
||||
Light: ''
|
||||
Main Color Theme:
|
||||
Main Color Theme: ''
|
||||
Red: ''
|
||||
Pink: ''
|
||||
Purple: ''
|
||||
Deep Purple: ''
|
||||
Indigo: ''
|
||||
Blue: ''
|
||||
Light Blue: ''
|
||||
Cyan: ''
|
||||
Teal: ''
|
||||
Green: ''
|
||||
Light Green: ''
|
||||
Lime: ''
|
||||
Yellow: ''
|
||||
Amber: ''
|
||||
Orange: ''
|
||||
Deep Orange: ''
|
||||
Secondary Color Theme: ''
|
||||
#* Main Color Theme
|
||||
Player Settings:
|
||||
Player Settings: ''
|
||||
Force Local Backend for Legacy Formats: ''
|
||||
Play Next Video: ''
|
||||
Turn on Subtitles by Default: ''
|
||||
Autoplay Videos: ''
|
||||
Proxy Videos Through Invidious: ''
|
||||
Autoplay Playlists: ''
|
||||
Enable Theatre Mode by Default: ''
|
||||
Default Volume: ''
|
||||
Default Playback Rate: ''
|
||||
Default Video Format:
|
||||
Default Video Format: ''
|
||||
Dash Formats: ''
|
||||
Legacy Formats: ''
|
||||
Audio Formats: ''
|
||||
Default Quality:
|
||||
Default Quality: ''
|
||||
Auto: ''
|
||||
144p: ''
|
||||
240p: ''
|
||||
360p: ''
|
||||
480p: ''
|
||||
720p: ''
|
||||
1080p: ''
|
||||
1440p: ''
|
||||
4k: ''
|
||||
8k: ''
|
||||
Privacy Settings:
|
||||
Privacy Settings: ''
|
||||
Remember History: ''
|
||||
Save Watched Progress: ''
|
||||
Clear Search Cache: ''
|
||||
Are you sure you want to clear out your search cache?: ''
|
||||
Search cache has been cleared: ''
|
||||
Remove Watch History: ''
|
||||
Are you sure you want to remove your entire watch history?: ''
|
||||
Watch history has been cleared: ''
|
||||
Remove All Subscriptions / Profiles: ''
|
||||
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: ''
|
||||
Subscription Settings:
|
||||
Subscription Settings: ''
|
||||
Hide Videos on Watch: ''
|
||||
Fetch Feeds from RSS: ''
|
||||
Manage Subscriptions: ''
|
||||
Distraction Free Settings:
|
||||
Distraction Free Settings: ''
|
||||
Hide Video Views: ''
|
||||
Hide Video Likes And Dislikes: ''
|
||||
Hide Channel Subscribers: ''
|
||||
Hide Comment Likes: ''
|
||||
Hide Recommended Videos: ''
|
||||
Hide Trending Videos: ''
|
||||
Hide Popular Videos: ''
|
||||
Hide Live Chat: ''
|
||||
Hide Active Subscriptions: ''
|
||||
Data Settings:
|
||||
Data Settings: ''
|
||||
Select Import Type: ''
|
||||
Select Export Type: ''
|
||||
Import Subscriptions: ''
|
||||
Import FreeTube: ''
|
||||
Import YouTube: ''
|
||||
Import NewPipe: ''
|
||||
Check for Legacy Subscriptions: ''
|
||||
Export Subscriptions: ''
|
||||
Export FreeTube: ''
|
||||
Export YouTube: ''
|
||||
Export NewPipe: ''
|
||||
Import History: ''
|
||||
Export History: ''
|
||||
Profile object has insufficient data, skipping item: ''
|
||||
All subscriptions and profiles have been successfully imported: ''
|
||||
All subscriptions have been successfully imported: ''
|
||||
One or more subscriptions were unable to be imported: ''
|
||||
Invalid subscriptions file: ''
|
||||
This might take a while, please wait: ''
|
||||
Invalid history file: ''
|
||||
Subscriptions have been successfully exported: ''
|
||||
History object has insufficient data, skipping item: ''
|
||||
All watched history has been successfully imported: ''
|
||||
All watched history has been successfully exported: ''
|
||||
Unable to read file: ''
|
||||
Unable to write file: ''
|
||||
Unknown data key: ''
|
||||
How do I import my subscriptions?: ''
|
||||
Manage Subscriptions: ''
|
||||
Proxy Settings:
|
||||
Proxy Settings: ''
|
||||
Enable Tor / Proxy: ''
|
||||
Proxy Protocol: ''
|
||||
Proxy Host: ''
|
||||
Proxy Port Number: ''
|
||||
Clicking on Test Proxy will send a request to: ''
|
||||
Test Proxy: ''
|
||||
Your Info: ''
|
||||
Ip: ''
|
||||
Country: ''
|
||||
Region: ''
|
||||
City: ''
|
||||
Error getting network information. Is your proxy configured properly?: ''
|
||||
About:
|
||||
#On About page
|
||||
About: ''
|
||||
Contact: ''
|
||||
Help: ''
|
||||
Useful Links: ''
|
||||
Donate: ''
|
||||
Beta: ''
|
||||
License: ''
|
||||
Email: ''
|
||||
Channel Rules: ''
|
||||
Report an Issue: ''
|
||||
Wiki: ''
|
||||
FAQ: ''
|
||||
Credits: ''
|
||||
Blog: ''
|
||||
Release Notes: ''
|
||||
Source Code: ''
|
||||
Website: ''
|
||||
Translate via Weblate: ''
|
||||
|
||||
Profile:
|
||||
Profile Select: ''
|
||||
All Channels: ''
|
||||
Profile Manager: ''
|
||||
Create New Profile: ''
|
||||
Edit Profile: ''
|
||||
Color Picker: ''
|
||||
Custom Color: ''
|
||||
Profile Preview: ''
|
||||
Create Profile: ''
|
||||
Update Profile: ''
|
||||
Make Default Profile: ''
|
||||
Delete Profile: ''
|
||||
Are you sure you want to delete this profile?: ''
|
||||
All subscriptions will also be deleted.: ''
|
||||
Profile could not be found: ''
|
||||
Your profile name cannot be empty: ''
|
||||
Profile has been created: ''
|
||||
Profile has been updated: ''
|
||||
Your default profile has been set to $: ''
|
||||
Removed $ from your profiles: ''
|
||||
Your default profile has been changed to your primary profile: ''
|
||||
$ is now the active profile: ''
|
||||
Subscription List: ''
|
||||
Other Channels: ''
|
||||
$ selected: ''
|
||||
Select All: ''
|
||||
Select None: ''
|
||||
Delete Selected: ''
|
||||
Add Selected To Profile: ''
|
||||
No channel(s) have been selected: ''
|
||||
? This is your primary profile. Are you sure you want to delete the selected channels? The
|
||||
same channels will be deleted in any profile they are found in.
|
||||
: ''
|
||||
Are you sure you want to delete the selected channels? This will not delete the channel from any other profile.: ''
|
||||
#On Channel Page
|
||||
Channel:
|
||||
Subscriber: ''
|
||||
Subscribers: ''
|
||||
Subscribe: ''
|
||||
Unsubscribe: ''
|
||||
Channel has been removed from your subscriptions: ''
|
||||
Removed subscription from $ other channel(s): ''
|
||||
Added channel to your subscriptions: ''
|
||||
Search Channel: ''
|
||||
Your search results have returned 0 results: ''
|
||||
Sort By: ''
|
||||
Videos:
|
||||
Videos: ''
|
||||
This channel does not currently have any videos: ''
|
||||
Sort Types:
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
Most Popular: ''
|
||||
Playlists:
|
||||
Playlists: ''
|
||||
This channel does not currently have any playlists: ''
|
||||
Sort Types:
|
||||
Last Video Added: ''
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
About:
|
||||
About: ''
|
||||
Channel Description: ''
|
||||
Featured Channels: ''
|
||||
Video:
|
||||
Mark As Watched: ''
|
||||
Remove From History: ''
|
||||
Video has been marked as watched: ''
|
||||
Video has been removed from your history: ''
|
||||
Save Video: ''
|
||||
Video has been saved: ''
|
||||
Video has been removed from your saved list: ''
|
||||
Open in YouTube: ''
|
||||
Copy YouTube Link: ''
|
||||
Open YouTube Embedded Player: ''
|
||||
Copy YouTube Embedded Player Link: ''
|
||||
Open in Invidious: ''
|
||||
Copy Invidious Link: ''
|
||||
Open Channel in YouTube: ''
|
||||
Copy YouTube Channel Link: ''
|
||||
Open Channel in Invidious: ''
|
||||
Copy Invidious Channel Link: ''
|
||||
View: ''
|
||||
Views: ''
|
||||
Loop Playlist: ''
|
||||
Shuffle Playlist: ''
|
||||
Reverse Playlist: ''
|
||||
Play Next Video: ''
|
||||
Play Previous Video: ''
|
||||
# Context is "X People Watching"
|
||||
Watching: ''
|
||||
Watched: ''
|
||||
Autoplay: ''
|
||||
Starting soon, please refresh the page to check again: ''
|
||||
# As in a Live Video
|
||||
Live: ''
|
||||
Live Now: ''
|
||||
Live Chat: ''
|
||||
Enable Live Chat: ''
|
||||
Live Chat is currently not supported in this build.: ''
|
||||
'Chat is disabled or the Live Stream has ended.': ''
|
||||
Live chat is enabled. Chat messages will appear here once sent.: ''
|
||||
'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': ''
|
||||
Download Video: ''
|
||||
video only: ''
|
||||
audio only: ''
|
||||
Audio:
|
||||
Low: ''
|
||||
Medium: ''
|
||||
High: ''
|
||||
Best: ''
|
||||
Published:
|
||||
Jan: ''
|
||||
Feb: ''
|
||||
Mar: ''
|
||||
Apr: ''
|
||||
May: ''
|
||||
Jun: ''
|
||||
Jul: ''
|
||||
Aug: ''
|
||||
Sep: ''
|
||||
Oct: ''
|
||||
Nov: ''
|
||||
Dec: ''
|
||||
Second: ''
|
||||
Seconds: ''
|
||||
Minute: ''
|
||||
Minutes: ''
|
||||
Hour: ''
|
||||
Hours: ''
|
||||
Day: ''
|
||||
Days: ''
|
||||
Week: ''
|
||||
Weeks: ''
|
||||
Month: ''
|
||||
Months: ''
|
||||
Year: ''
|
||||
Years: ''
|
||||
Ago: ''
|
||||
Upcoming: ''
|
||||
Published on: ''
|
||||
Streamed on: ''
|
||||
Started streaming on: ''
|
||||
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
||||
Publicationtemplate: ''
|
||||
#& Videos
|
||||
Videos:
|
||||
#& Sort By
|
||||
Sort By:
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
#& Most Popular
|
||||
#& Playlists
|
||||
Playlist:
|
||||
#& About
|
||||
View Full Playlist: ''
|
||||
Videos: ''
|
||||
View: ''
|
||||
Views: ''
|
||||
Last Updated On: ''
|
||||
Share Playlist:
|
||||
Share Playlist: ''
|
||||
Copy YouTube Link: ''
|
||||
Open in YouTube: ''
|
||||
Copy Invidious Link: ''
|
||||
Open in Invidious: ''
|
||||
|
||||
# On Video Watch Page
|
||||
#* Published
|
||||
#& Views
|
||||
Toggle Theatre Mode: ''
|
||||
Change Format:
|
||||
Change Video Formats: ''
|
||||
Use Dash Formats: ''
|
||||
Use Legacy Formats: ''
|
||||
Use Audio Formats: ''
|
||||
Dash formats are not available for this video: ''
|
||||
Audio formats are not available for this video: ''
|
||||
Share:
|
||||
Share Video: ''
|
||||
Include Timestamp: ''
|
||||
Copy Link: ''
|
||||
Open Link: ''
|
||||
Copy Embed: ''
|
||||
Open Embed: ''
|
||||
# On Click
|
||||
Invidious URL copied to clipboard: ''
|
||||
Invidious Embed URL copied to clipboard: ''
|
||||
Invidious Channel URL copied to clipboard: ''
|
||||
YouTube URL copied to clipboard: ''
|
||||
YouTube Embed URL copied to clipboard: ''
|
||||
YouTube Channel URL copied to clipboard: ''
|
||||
|
||||
Mini Player: ''
|
||||
Comments:
|
||||
Comments: ''
|
||||
Click to View Comments: ''
|
||||
Getting comment replies, please wait: ''
|
||||
There are no more comments for this video: ''
|
||||
Show Comments: ''
|
||||
Hide Comments: ''
|
||||
Sort by: ''
|
||||
Top comments: ''
|
||||
Newest first: ''
|
||||
# Context: View 10 Replies, View 1 Reply
|
||||
View: ''
|
||||
Hide: ''
|
||||
Replies: ''
|
||||
Reply: ''
|
||||
There are no comments available for this video: ''
|
||||
Load More Comments: ''
|
||||
No more comments available: ''
|
||||
Up Next: ''
|
||||
|
||||
#Tooltips
|
||||
Tooltips:
|
||||
General Settings:
|
||||
Preferred API Backend: ''
|
||||
Fallback to Non-Preferred Backend on Failure: ''
|
||||
Thumbnail Preference: ''
|
||||
Invidious Instance: ''
|
||||
Region for Trending: ''
|
||||
Player Settings:
|
||||
Force Local Backend for Legacy Formats: ''
|
||||
Proxy Videos Through Invidious: ''
|
||||
Default Video Format: ''
|
||||
Subscription Settings:
|
||||
Fetch Feeds from RSS: ''
|
||||
|
||||
# Toast Messages
|
||||
Local API Error (Click to copy): ''
|
||||
Invidious API Error (Click to copy): ''
|
||||
Falling back to Invidious API: ''
|
||||
Falling back to the local API: ''
|
||||
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
|
||||
Subscriptions have not yet been implemented: ''
|
||||
Loop is now disabled: ''
|
||||
Loop is now enabled: ''
|
||||
Shuffle is now disabled: ''
|
||||
Shuffle is now enabled: ''
|
||||
The playlist has been reversed: ''
|
||||
Playing Next Video: ''
|
||||
Playing Previous Video: ''
|
||||
Playing next video in 5 seconds. Click to cancel: ''
|
||||
Canceled next video autoplay: ''
|
||||
'The playlist has ended. Enable loop to continue playing': ''
|
||||
|
||||
Yes: ''
|
||||
No: ''
|
|
@ -0,0 +1,535 @@
|
|||
# Put the name of your locale in the same language
|
||||
Locale Name: 'Bosanski'
|
||||
FreeTube: 'FreeTube'
|
||||
# Currently on Subscriptions, Playlists, and History
|
||||
'This part of the app is not ready yet. Come back later when progress has been made.': >-
|
||||
Ovaj dio aplikacije još nije spreman. Vratite se kasnije kad se postigne napredak.
|
||||
|
||||
# Webkit Menu Bar
|
||||
File: 'Fajl'
|
||||
Quit: 'Napusti'
|
||||
Edit: 'Uredi'
|
||||
Undo: 'Ukini'
|
||||
Redo: 'Ponovi'
|
||||
Cut: 'Izreži'
|
||||
Copy: 'Kopiraj'
|
||||
Paste: 'Umetni'
|
||||
Delete: 'Izbriši'
|
||||
Select all: 'Odabri sve'
|
||||
Reload: 'Ponovo učitaj'
|
||||
Force Reload: 'Silom učitaj ponovo'
|
||||
Toggle Developer Tools: 'Uključi alate za programere'
|
||||
Actual size: 'Prirodna veličina'
|
||||
Zoom in: 'Približi'
|
||||
Zoom out: 'Umanji'
|
||||
Toggle fullscreen: 'Prebaci preko cijelog ekrana'
|
||||
Window: 'Prozor'
|
||||
Minimize: 'Smanji'
|
||||
Close: 'Zatvori'
|
||||
Back: 'Nazad'
|
||||
Forward: 'Unapred'
|
||||
|
||||
Version $ is now available! Click for more details: 'Verzija $ je sada dostupna!
|
||||
Kliknite za više detalja'
|
||||
Download From Site: 'Instaliraj preko stranice'
|
||||
A new blog is now available, $. Click to view more: 'Sada je dostupan novi blog, $.
|
||||
Kliknite da vidite više'
|
||||
|
||||
# Search Bar
|
||||
Search / Go to URL: 'Pretražite / idite na URL'
|
||||
# In Filter Button
|
||||
Search Filters:
|
||||
Search Filters: 'Pretraži filtere'
|
||||
Sort By:
|
||||
Sort By: 'Poredaj po'
|
||||
Most Relevant: 'Naj relevantnije'
|
||||
Rating: 'Ocjena'
|
||||
Upload Date: 'Datum uploada'
|
||||
View Count: 'Broj pregleda'
|
||||
Time:
|
||||
Time: 'Vrjeme'
|
||||
Any Time: 'Bilo kada'
|
||||
Last Hour: 'Zadnji sat'
|
||||
Today: 'Danas'
|
||||
This Week: 'Ove sedmice'
|
||||
This Month: 'Ovog Mjeseca'
|
||||
This Year: 'Ove godine'
|
||||
Type:
|
||||
Type: 'Vrsta'
|
||||
All Types: 'Sve vrste'
|
||||
Videos: 'Video'
|
||||
Channels: 'Kanali'
|
||||
#& Playlists
|
||||
Duration:
|
||||
Duration: 'Trajanje'
|
||||
All Durations: 'Sva trajanja'
|
||||
Short (< 4 minutes): 'Kratko (<4 minute)'
|
||||
Long (> 20 minutes): 'Dugo (>20 minuta)'
|
||||
# On Search Page
|
||||
Search Results: 'Rezultati pretrage'
|
||||
Fetching results. Please wait: 'Dohvaćanje rezultata. Molimo sačekajte'
|
||||
Fetch more results: 'Dohvati više rezultata'
|
||||
# Sidebar
|
||||
Subscriptions:
|
||||
# On Subscriptions Page
|
||||
Subscriptions: 'Pretplate'
|
||||
Latest Subscriptions: 'Najnovije pretplate'
|
||||
This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: 'Ovaj
|
||||
profil ima veliki broj pretplata. Prisiljavanje RSS-a da izbjegne ograničenje
|
||||
brzine'
|
||||
'Your Subscription list is currently empty. Start adding subscriptions to see them here.': 'Vaša
|
||||
lista pretplata je trenutno prazna. Počnite dodavati pretplate da biste ih vidjeli
|
||||
ovdje.'
|
||||
'Getting Subscriptions. Please wait.': 'Preuzimanje pretplata. Molimo sačekajte.'
|
||||
Refresh Subscriptions: 'Osvježi pretplate'
|
||||
Load More Videos: 'Očitaj više videozapisa'
|
||||
Trending: 'U trendu'
|
||||
Most Popular: 'Naj popularnije'
|
||||
Playlists: 'playliste'
|
||||
User Playlists:
|
||||
Your Playlists: 'Tvoje playliste'
|
||||
History:
|
||||
# On History Page
|
||||
History: 'Istorija'
|
||||
Watch History: 'Istorija gledanja'
|
||||
Your history list is currently empty.: 'Vaša lista istorije je trenutno prazna.'
|
||||
Settings:
|
||||
# On Settings Page
|
||||
Settings: 'Postavke'
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: 'Aplikacija
|
||||
se treba restartovati da bi promjene stupile na snagu. Restartuj i primijeniti
|
||||
promjenu?'
|
||||
General Settings:
|
||||
General Settings: 'Generalne postavke'
|
||||
Check for Updates: 'Provjeri ima li update'
|
||||
Check for Latest Blog Posts: 'Potraži najnovije objave na blogu'
|
||||
Fallback to Non-Preferred Backend on Failure: 'Vraćanje na neželjeni backend u
|
||||
slučaju neuspjeha'
|
||||
Enable Search Suggestions: 'Omogući prijedloge pretraživanja'
|
||||
Default Landing Page: 'Zadana odredišna stranica'
|
||||
Locale Preference: 'Jezik'
|
||||
Preferred API Backend:
|
||||
Preferred API Backend: 'Poželjni API Backend'
|
||||
Local API: 'Lokalni API'
|
||||
Invidious API: 'Invidious API'
|
||||
Video View Type:
|
||||
Video View Type: 'Način prikazanja videa'
|
||||
Grid: 'Popločan'
|
||||
List: 'Popis'
|
||||
Thumbnail Preference:
|
||||
Thumbnail Preference: 'Preferencija minijature'
|
||||
Default: 'Standard'
|
||||
Beginning: 'Početak'
|
||||
Middle: 'Sredina'
|
||||
End: 'Kraj'
|
||||
'Invidious Instance (Default is https://invidious.snopyta.org)': 'Invidious primjer
|
||||
(standard je https://invidious.snopyta.org)'
|
||||
Region for Trending: 'Regiona za trend'
|
||||
#! List countries
|
||||
Theme Settings:
|
||||
Theme Settings: 'Postavke teme'
|
||||
Match Top Bar with Main Color: 'Koristi glavnu boju u gornjoj traci'
|
||||
Expand Side Bar by Default: ''
|
||||
Disable Smooth Scrolling: ''
|
||||
UI Scale: ''
|
||||
Base Theme:
|
||||
Base Theme: ''
|
||||
Black: ''
|
||||
Dark: ''
|
||||
Light: ''
|
||||
Main Color Theme:
|
||||
Main Color Theme: ''
|
||||
Red: ''
|
||||
Pink: ''
|
||||
Purple: ''
|
||||
Deep Purple: ''
|
||||
Indigo: ''
|
||||
Blue: ''
|
||||
Light Blue: ''
|
||||
Cyan: ''
|
||||
Teal: ''
|
||||
Green: ''
|
||||
Light Green: ''
|
||||
Lime: ''
|
||||
Yellow: ''
|
||||
Amber: ''
|
||||
Orange: ''
|
||||
Deep Orange: ''
|
||||
Secondary Color Theme: ''
|
||||
#* Main Color Theme
|
||||
Player Settings:
|
||||
Player Settings: ''
|
||||
Force Local Backend for Legacy Formats: ''
|
||||
Play Next Video: ''
|
||||
Turn on Subtitles by Default: ''
|
||||
Autoplay Videos: ''
|
||||
Proxy Videos Through Invidious: ''
|
||||
Autoplay Playlists: ''
|
||||
Enable Theatre Mode by Default: ''
|
||||
Default Volume: ''
|
||||
Default Playback Rate: ''
|
||||
Default Video Format:
|
||||
Default Video Format: ''
|
||||
Dash Formats: ''
|
||||
Legacy Formats: ''
|
||||
Audio Formats: ''
|
||||
Default Quality:
|
||||
Default Quality: ''
|
||||
Auto: ''
|
||||
144p: ''
|
||||
240p: ''
|
||||
360p: ''
|
||||
480p: ''
|
||||
720p: ''
|
||||
1080p: ''
|
||||
1440p: ''
|
||||
4k: ''
|
||||
8k: ''
|
||||
Privacy Settings:
|
||||
Privacy Settings: ''
|
||||
Remember History: ''
|
||||
Save Watched Progress: ''
|
||||
Clear Search Cache: ''
|
||||
Are you sure you want to clear out your search cache?: ''
|
||||
Search cache has been cleared: ''
|
||||
Remove Watch History: ''
|
||||
Are you sure you want to remove your entire watch history?: ''
|
||||
Watch history has been cleared: ''
|
||||
Remove All Subscriptions / Profiles: ''
|
||||
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: ''
|
||||
Subscription Settings:
|
||||
Subscription Settings: ''
|
||||
Hide Videos on Watch: ''
|
||||
Fetch Feeds from RSS: ''
|
||||
Manage Subscriptions: ''
|
||||
Distraction Free Settings:
|
||||
Distraction Free Settings: ''
|
||||
Hide Video Views: ''
|
||||
Hide Video Likes And Dislikes: ''
|
||||
Hide Channel Subscribers: ''
|
||||
Hide Comment Likes: ''
|
||||
Hide Recommended Videos: ''
|
||||
Hide Trending Videos: ''
|
||||
Hide Popular Videos: ''
|
||||
Hide Live Chat: ''
|
||||
Data Settings:
|
||||
Data Settings: ''
|
||||
Select Import Type: ''
|
||||
Select Export Type: ''
|
||||
Import Subscriptions: ''
|
||||
Import FreeTube: ''
|
||||
Import YouTube: ''
|
||||
Import NewPipe: ''
|
||||
Check for Legacy Subscriptions: ''
|
||||
Export Subscriptions: ''
|
||||
Export FreeTube: ''
|
||||
Export YouTube: ''
|
||||
Export NewPipe: ''
|
||||
Import History: ''
|
||||
Export History: ''
|
||||
Profile object has insufficient data, skipping item: ''
|
||||
All subscriptions and profiles have been successfully imported: ''
|
||||
All subscriptions have been successfully imported: ''
|
||||
One or more subscriptions were unable to be imported: ''
|
||||
Invalid subscriptions file: ''
|
||||
This might take a while, please wait: ''
|
||||
Invalid history file: ''
|
||||
Subscriptions have been successfully exported: ''
|
||||
History object has insufficient data, skipping item: ''
|
||||
All watched history has been successfully imported: ''
|
||||
All watched history has been successfully exported: ''
|
||||
Unable to read file: ''
|
||||
Unable to write file: ''
|
||||
Unknown data key: ''
|
||||
How do I import my subscriptions?: ''
|
||||
Advanced Settings:
|
||||
Advanced Settings: ''
|
||||
Enable Debug Mode (Prints data to the console): ''
|
||||
'Proxy Address (Example: SOCKS5://127.0.0.1:9050 )': ''
|
||||
'Clicking "TEST PROXY" button will send a request to https://ipinfo.io/json': ''
|
||||
Use Tor / Proxy for API calls: ''
|
||||
TEST PROXY: ''
|
||||
#& Invidious Instance (Default is https://invidious.snopyta.org)
|
||||
See Public Instances: ''
|
||||
Clear History:
|
||||
Clear History: ''
|
||||
# On Click
|
||||
Are you sure you want to delete your history?: ''
|
||||
#& Yes
|
||||
#& No
|
||||
Clear Subscriptions:
|
||||
Clear Subscriptions: ''
|
||||
# On Click
|
||||
Are you sure you want to remove all subscriptions?: ''
|
||||
#& Yes
|
||||
#& No
|
||||
|
||||
About:
|
||||
#On About page
|
||||
About: ''
|
||||
#& About
|
||||
'This software is FOSS and released under the GNU Affero General Public License v3.0.': ''
|
||||
|
||||
'Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.': >
|
||||
|
||||
Thank you very much to the People and Projects that make FreeTube possible!: ''
|
||||
|
||||
'Want to chat? Join our Element / Matrix Server . Please check the rules before joining.': ''
|
||||
|
||||
'Looking for help? Check out our Wiki page.': ''
|
||||
|
||||
Check out our Firefox extension!: ''
|
||||
|
||||
'If you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin address.': ''
|
||||
|
||||
#~ 'BTC: 1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS'
|
||||
|
||||
Latest FreeTube News: ''
|
||||
|
||||
Profile:
|
||||
Profile Select: ''
|
||||
All Channels: ''
|
||||
Profile Manager: ''
|
||||
Create New Profile: ''
|
||||
Edit Profile: ''
|
||||
Color Picker: ''
|
||||
Custom Color: ''
|
||||
Profile Preview: ''
|
||||
Create Profile: ''
|
||||
Update Profile: ''
|
||||
Make Default Profile: ''
|
||||
Delete Profile: ''
|
||||
Are you sure you want to delete this profile?: ''
|
||||
All subscriptions will also be deleted.: ''
|
||||
Profile could not be found: ''
|
||||
Your profile name cannot be empty: ''
|
||||
Profile has been created: ''
|
||||
Profile has been updated: ''
|
||||
Your default profile has been set to $: ''
|
||||
Removed $ from your profiles: ''
|
||||
Your default profile has been changed to your primary profile: ''
|
||||
$ is now the active profile: ''
|
||||
Subscription List: ''
|
||||
Other Channels: ''
|
||||
$ selected: ''
|
||||
Select All: ''
|
||||
Select None: ''
|
||||
Delete Selected: ''
|
||||
Add Selected To Profile: ''
|
||||
No channel(s) have been selected: ''
|
||||
? This is your primary profile. Are you sure you want to delete the selected channels? The
|
||||
same channels will be deleted in any profile they are found in.
|
||||
: ''
|
||||
Are you sure you want to delete the selected channels? This will not delete the channel from any other profile.: ''
|
||||
#On Channel Page
|
||||
Channel:
|
||||
Subscriber: ''
|
||||
Subscribers: ''
|
||||
Subscribe: ''
|
||||
Unsubscribe: ''
|
||||
Channel has been removed from your subscriptions: ''
|
||||
Removed subscription from $ other channel(s): ''
|
||||
Added channel to your subscriptions: ''
|
||||
Search Channel: ''
|
||||
Your search results have returned 0 results: ''
|
||||
Sort By: ''
|
||||
Videos:
|
||||
Videos: ''
|
||||
This channel does not currently have any videos: ''
|
||||
Sort Types:
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
Most Popular: ''
|
||||
Playlists:
|
||||
Playlists: ''
|
||||
This channel does not currently have any playlists: ''
|
||||
Sort Types:
|
||||
Last Video Added: ''
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
About:
|
||||
About: ''
|
||||
Channel Description: ''
|
||||
Featured Channels: ''
|
||||
Video:
|
||||
Mark As Watched: ''
|
||||
Remove From History: ''
|
||||
Video has been marked as watched: ''
|
||||
Video has been removed from your history: ''
|
||||
Open in YouTube: ''
|
||||
Copy YouTube Link: ''
|
||||
Open YouTube Embedded Player: ''
|
||||
Copy YouTube Embedded Player Link: ''
|
||||
Open in Invidious: ''
|
||||
Copy Invidious Link: ''
|
||||
Open Channel in YouTube: ''
|
||||
Copy YouTube Channel Link: ''
|
||||
Open Channel in Invidious: ''
|
||||
Copy Invidious Channel Link: ''
|
||||
View: ''
|
||||
Views: ''
|
||||
Loop Playlist: ''
|
||||
Shuffle Playlist: ''
|
||||
Reverse Playlist: ''
|
||||
Play Next Video: ''
|
||||
Play Previous Video: ''
|
||||
# Context is "X People Watching"
|
||||
Watching: ''
|
||||
Watched: ''
|
||||
Autoplay: ''
|
||||
Starting soon, please refresh the page to check again: ''
|
||||
# As in a Live Video
|
||||
Live: ''
|
||||
Live Now: ''
|
||||
Live Chat: ''
|
||||
Enable Live Chat: ''
|
||||
Live Chat is currently not supported in this build.: ''
|
||||
'Chat is disabled or the Live Stream has ended.': ''
|
||||
Live chat is enabled. Chat messages will appear here once sent.: ''
|
||||
'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': ''
|
||||
Download Video: ''
|
||||
video only: ''
|
||||
audio only: ''
|
||||
Audio:
|
||||
Low: ''
|
||||
Medium: ''
|
||||
High: ''
|
||||
Best: ''
|
||||
Published:
|
||||
Jan: ''
|
||||
Feb: ''
|
||||
Mar: ''
|
||||
Apr: ''
|
||||
May: ''
|
||||
Jun: ''
|
||||
Jul: ''
|
||||
Aug: ''
|
||||
Sep: ''
|
||||
Oct: ''
|
||||
Nov: ''
|
||||
Dec: ''
|
||||
Second: ''
|
||||
Seconds: ''
|
||||
Minute: ''
|
||||
Minutes: ''
|
||||
Hour: ''
|
||||
Hours: ''
|
||||
Day: ''
|
||||
Days: ''
|
||||
Week: ''
|
||||
Weeks: ''
|
||||
Month: ''
|
||||
Months: ''
|
||||
Year: ''
|
||||
Years: ''
|
||||
Ago: ''
|
||||
Upcoming: ''
|
||||
Published on: ''
|
||||
Streamed on: ''
|
||||
Started streaming on: ''
|
||||
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
||||
Publicationtemplate: ''
|
||||
#& Videos
|
||||
Videos:
|
||||
#& Sort By
|
||||
Sort By:
|
||||
Newest: ''
|
||||
Oldest: ''
|
||||
#& Most Popular
|
||||
#& Playlists
|
||||
Playlist:
|
||||
#& About
|
||||
View Full Playlist: ''
|
||||
Videos: ''
|
||||
View: ''
|
||||
Views: ''
|
||||
Last Updated On: ''
|
||||
Share Playlist:
|
||||
Share Playlist: ''
|
||||
Copy YouTube Link: ''
|
||||
Open in YouTube: ''
|
||||
Copy Invidious Link: ''
|
||||
Open in Invidious: ''
|
||||
|
||||
# On Video Watch Page
|
||||
#* Published
|
||||
#& Views
|
||||
Toggle Theatre Mode: ''
|
||||
Change Format:
|
||||
Change Video Formats: ''
|
||||
Use Dash Formats: ''
|
||||
Use Legacy Formats: ''
|
||||
Use Audio Formats: ''
|
||||
Dash formats are not available for this video: ''
|
||||
Audio formats are not available for this video: ''
|
||||
Share:
|
||||
Share Video: ''
|
||||
Include Timestamp: ''
|
||||
Copy Link: ''
|
||||
Open Link: ''
|
||||
Copy Embed: ''
|
||||
Open Embed: ''
|
||||
# On Click
|
||||
Invidious URL copied to clipboard: ''
|
||||
Invidious Embed URL copied to clipboard: ''
|
||||
Invidious Channel URL copied to clipboard: ''
|
||||
YouTube URL copied to clipboard: ''
|
||||
YouTube Embed URL copied to clipboard: ''
|
||||
YouTube Channel URL copied to clipboard: ''
|
||||
|
||||
Mini Player: ''
|
||||
Comments:
|
||||
Comments: ''
|
||||
Click to View Comments: ''
|
||||
Getting comment replies, please wait: ''
|
||||
There are no more comments for this video: ''
|
||||
Show Comments: ''
|
||||
Hide Comments: ''
|
||||
Sort by: ''
|
||||
Top comments: ''
|
||||
Newest first: ''
|
||||
# Context: View 10 Replies, View 1 Reply
|
||||
View: ''
|
||||
Hide: ''
|
||||
Replies: ''
|
||||
Reply: ''
|
||||
There are no comments available for this video: ''
|
||||
Load More Comments: ''
|
||||
No more comments available: ''
|
||||
Up Next: ''
|
||||
|
||||
#Tooltips
|
||||
Tooltips:
|
||||
General Settings:
|
||||
Preferred API Backend: ''
|
||||
Fallback to Non-Preferred Backend on Failure: ''
|
||||
Thumbnail Preference: ''
|
||||
Invidious Instance: ''
|
||||
Region for Trending: ''
|
||||
Player Settings:
|
||||
Force Local Backend for Legacy Formats: ''
|
||||
Proxy Videos Through Invidious: ''
|
||||
Default Video Format: ''
|
||||
Subscription Settings:
|
||||
Fetch Feeds from RSS: ''
|
||||
|
||||
# Toast Messages
|
||||
Local API Error (Click to copy): ''
|
||||
Invidious API Error (Click to copy): ''
|
||||
Falling back to Invidious API: ''
|
||||
Falling back to the local API: ''
|
||||
This video is unavailable because of missing formats. This can happen due to country unavailability.: ''
|
||||
Subscriptions have not yet been implemented: ''
|
||||
Loop is now disabled: ''
|
||||
Loop is now enabled: ''
|
||||
Shuffle is now disabled: ''
|
||||
Shuffle is now enabled: ''
|
||||
The playlist has been reversed: ''
|
||||
Playing Next Video: ''
|
||||
Playing Previous Video: ''
|
||||
Playing next video in 5 seconds. Click to cancel: ''
|
||||
Canceled next video autoplay: ''
|
||||
'The playlist has ended. Enable loop to continue playing': ''
|
||||
|
||||
Yes: ''
|
||||
No: 'Ne'
|
|
@ -132,8 +132,8 @@ Settings:
|
|||
Base Theme:
|
||||
Base Theme: 'Základní motiv'
|
||||
Black: 'Černý'
|
||||
Dark: 'Temný'
|
||||
Light: 'Lehký'
|
||||
Dark: 'Tmavý'
|
||||
Light: 'Světlý'
|
||||
Main Color Theme:
|
||||
Main Color Theme: 'Hlavní barevný motiv'
|
||||
Red: 'Červený'
|
||||
|
@ -212,6 +212,7 @@ Settings:
|
|||
Hide Trending Videos: 'Skrýt trendy'
|
||||
Hide Popular Videos: 'Skrýt populární videa'
|
||||
Hide Live Chat: 'Skrýt chat'
|
||||
Hide Active Subscriptions: Skrýt aktivní odběry
|
||||
Data Settings:
|
||||
Data Settings: 'Nastavení dat'
|
||||
Select Import Type: 'Vybrat typ importu'
|
||||
|
@ -458,7 +459,7 @@ Video:
|
|||
Upcoming: 'Premiéra'
|
||||
Published on: 'Publikováno'
|
||||
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
||||
Publicationtemplate: '$ % před'
|
||||
Publicationtemplate: 'před $ %'
|
||||
#& Videos
|
||||
Started streaming on: Začátek vysílání
|
||||
Streamed on: Vysíláno
|
||||
|
|
|
@ -6,7 +6,7 @@ FreeTube: FreeTube
|
|||
|
||||
# Webkit Menu Bar
|
||||
File: Datei
|
||||
Quit: Verlassen
|
||||
Quit: Beenden
|
||||
Edit: Bearbeiten
|
||||
Undo: Rückgängig
|
||||
Redo: Wiederherstellen
|
||||
|
@ -16,7 +16,7 @@ Paste: Einfügen
|
|||
Delete: Löschen
|
||||
Select all: Alles auswählen
|
||||
Reload: Aktualisieren
|
||||
Force Reload: Erzwinge Aktualisierung
|
||||
Force Reload: Aktualisierung erzwingen
|
||||
Toggle Developer Tools: Aktiviere Entwicklerwerkzeuge
|
||||
Actual size: Originalgröße
|
||||
Zoom in: Vergrößern
|
||||
|
@ -116,7 +116,7 @@ Settings:
|
|||
(Standard ist https://invidious.snopyta.org)
|
||||
Region for Trending: Region für Trends
|
||||
#! List countries
|
||||
Check for Latest Blog Posts: Nach aktuellstem Blogeintrag suchen
|
||||
Check for Latest Blog Posts: Nach aktuellsten Blogeinträgen suchen
|
||||
Check for Updates: Nach Aktualisierungen suchen
|
||||
Theme Settings:
|
||||
Theme Settings: Thema Einstellungen
|
||||
|
@ -151,7 +151,7 @@ Settings:
|
|||
Expand Side Bar by Default: Seitenleiste standardmäßig erweitern
|
||||
Player Settings:
|
||||
Player Settings: Videoabspieler-Einstellungen
|
||||
Force Local Backend for Legacy Formats: Lokales System für Altformat erzwingen
|
||||
Force Local Backend for Legacy Formats: Lokales System für Legacy Formate erzwingen
|
||||
Remember History: Verlauf speichern
|
||||
Play Next Video: Spiele nächstes Video
|
||||
Turn on Subtitles by Default: Untertitel standardmäßig aktivieren
|
||||
|
@ -282,6 +282,7 @@ Settings:
|
|||
Hide Video Likes And Dislikes: Videobewertungen verbergen
|
||||
Hide Video Views: Video-Aufrufe verbergen
|
||||
Distraction Free Settings: Einstellungen für ablenkungsfreien Modus
|
||||
Hide Active Subscriptions: Aktive Abonnements ausblenden
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: Um
|
||||
die Änderungen anzuwenden muss die Anwendung neustarten. Jetzt neustarten und
|
||||
Änderungen aktivieren?
|
||||
|
@ -320,6 +321,23 @@ About:
|
|||
#On Channel Page
|
||||
This software is FOSS and released under the GNU Affero General Public License v3.0.: Diese
|
||||
freie Software ist unter der AGPL-3.0 lizenziert.
|
||||
Translate via Weblate: Auf Weblate übersetzen
|
||||
Website: Webseite
|
||||
Source Code: Quellcode
|
||||
Release Notes: Versionshinweise
|
||||
Blog: Blog
|
||||
Credits: Beiträge
|
||||
FAQ: Häufig gestellte Fragen
|
||||
Wiki: Wiki
|
||||
Report an Issue: Fehler melden
|
||||
Channel Rules: Kanalregeln
|
||||
Email: Email
|
||||
License: Lizenz
|
||||
Beta: Beta
|
||||
Donate: Spenden
|
||||
Useful Links: Nützliche Links
|
||||
Help: Hilfe
|
||||
Contact: Kontakt
|
||||
Channel:
|
||||
Subscriber: Abonnement
|
||||
Subscribers: Abonnements
|
||||
|
@ -468,7 +486,7 @@ Share Playlist:
|
|||
# On Video Watch Page
|
||||
#* Published
|
||||
#& Views
|
||||
Toggle Theatre Mode: Aktiviere Kinomodus
|
||||
Toggle Theatre Mode: Kinomodus umschalten
|
||||
Change Format:
|
||||
Change Video Formats: Ändere Videoformat
|
||||
Use Dash Formats: Nutze DASH-Format
|
||||
|
|
|
@ -31,7 +31,7 @@ Back: 'Μετάβαση πίσω'
|
|||
Forward: 'Μετάβαση μπροστά'
|
||||
|
||||
# Search Bar
|
||||
Search / Go to URL: 'Αναζήτηση/Τοποθετήστε Διεύθυνση URL'
|
||||
Search / Go to URL: 'Αναζήτηση/Μετάβαση στη URL'
|
||||
# In Filter Button
|
||||
Search Filters:
|
||||
Search Filters: 'Φίλτρα αναζήτησης'
|
||||
|
@ -39,16 +39,16 @@ Search Filters:
|
|||
Sort By: 'Ταξινόμηση κατά'
|
||||
Most Relevant: 'Πιο σχετικό'
|
||||
Rating: 'Αξιολόγηση'
|
||||
Upload Date: 'Ημερομηνία αποστολής'
|
||||
Upload Date: 'Ημερομηνία μεταφόρτωσης'
|
||||
View Count: 'Πλήθος Προβολών'
|
||||
Time:
|
||||
Time: 'Χρόνος'
|
||||
Any Time: 'Οποιαδήποτε περίοδος'
|
||||
Last Hour: 'Τελευταία ώρα'
|
||||
Time: 'Ώρα'
|
||||
Any Time: 'Οποτεδήποτε'
|
||||
Last Hour: 'Τελευταίας ώρας'
|
||||
Today: 'Σήμερα'
|
||||
This Week: 'Τρέχουσα Εβδομάδα'
|
||||
This Month: 'Αυτό το μήνα'
|
||||
This Year: 'Αυτού του χρόνου'
|
||||
This Year: 'Τρέχων έτος'
|
||||
Type:
|
||||
Type: 'Είδος'
|
||||
All Types: 'Όλα τα είδη'
|
||||
|
@ -70,8 +70,8 @@ Subscriptions:
|
|||
Subscriptions: 'Εγγραφές'
|
||||
Latest Subscriptions: 'Τελευταίες Εγγραφές'
|
||||
'Your Subscription list is currently empty. Start adding subscriptions to see them here.': 'Η
|
||||
λίστα εγγραφών σας είναι προς το παρόν κενή. Ξεκινήστε να προσθέτετε εγγραφές/συνδρομές
|
||||
για να τις παρακολουθείτε εδώ.'
|
||||
λίστα συνδρομών σας είναι προς το παρόν κενή. Προσθέστε συνδρομές για να τις παρακολουθείτε
|
||||
από εδώ.'
|
||||
'Getting Subscriptions. Please wait.': 'Ανάκτηση Εγγραφών/Συνδρομών. Παρακαλώ περιμένετε.'
|
||||
Refresh Subscriptions: 'Ανανέωση Εγγραφών/Συνδρομών'
|
||||
This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: Αυτό
|
||||
|
@ -98,7 +98,7 @@ Settings:
|
|||
υποστήριξης σε περίπτωση αποτυχίας'
|
||||
Enable Search Suggestions: 'Ενεργοποίηση προτάσεων αναζήτησης'
|
||||
Default Landing Page: 'Προεπιλεγμένη σελίδα προορισμού'
|
||||
Locale Preference: 'Προτιμώμενη Γλώσσα'
|
||||
Locale Preference: 'Προτιμήσεις γλώσσας'
|
||||
Preferred API Backend:
|
||||
Preferred API Backend: 'Προτιμώμενο συστήμα (API)'
|
||||
Local API: 'Τοπική διεπαφή προγραμματισμού εφαρμογών (API)'
|
||||
|
@ -114,7 +114,7 @@ Settings:
|
|||
Middle: 'Μέση'
|
||||
End: 'Τέλος'
|
||||
'Invidious Instance (Default is https://invidious.snopyta.org)': 'Διακομιστής
|
||||
Invidious (Ο προκαθορισμένος είναι https://invidious.snopyta.org)'
|
||||
Invidious (προεπιλογή https://invidious.snopyta.org)'
|
||||
Region for Trending: 'Περιοχή που καθορίζει την καρτέλα των τάσεων'
|
||||
#! List countries
|
||||
Check for Latest Blog Posts: Ελέγξτε για τις τελευταίες δημοσιεύσεις ιστολογίου
|
||||
|
|
|
@ -86,6 +86,8 @@ Most Popular: Most Popular
|
|||
Playlists: Playlists
|
||||
User Playlists:
|
||||
Your Playlists: Your Playlists
|
||||
Playlist Message: This page is not reflective of fully working playlists. It only lists videos that you have saved or favorited. When the work has finished, all videos currently here will be migrated to a 'Favorites' playlist.
|
||||
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: Your saved videos are empty. Click on the save button on the corner of a video to have it listed here
|
||||
History:
|
||||
# On History Page
|
||||
History: History
|
||||
|
@ -213,6 +215,7 @@ Settings:
|
|||
Hide Trending Videos: Hide Trending Videos
|
||||
Hide Popular Videos: Hide Popular Videos
|
||||
Hide Live Chat: Hide Live Chat
|
||||
Hide Active Subscriptions: Hide Active Subscriptions
|
||||
Data Settings:
|
||||
Data Settings: Data Settings
|
||||
Select Import Type: Select Import Type
|
||||
|
@ -251,62 +254,48 @@ Settings:
|
|||
Unable to write file: Unable to write file
|
||||
Unknown data key: Unknown data key
|
||||
How do I import my subscriptions?: How do I import my subscriptions?
|
||||
Advanced Settings:
|
||||
Advanced Settings: Advanced Settings
|
||||
Enable Debug Mode (Prints data to the console): Enable Debug Mode (Prints data
|
||||
to the console)
|
||||
'Proxy Address (Example: SOCKS5://127.0.0.1:9050 )': 'Proxy Address (Example:
|
||||
SOCKS5://127.0.0.1:9050 )'
|
||||
'Clicking "TEST PROXY" button will send a request to https://ipinfo.io/json': Clicking
|
||||
"TEST PROXY" button will send a request to https://ipinfo.io/json
|
||||
Use Tor / Proxy for API calls: Use Tor / Proxy for API calls
|
||||
TEST PROXY: TEST PROXY
|
||||
#& Invidious Instance (Default is https://invidious.snopyta.org)
|
||||
See Public Instances: See Public Instances
|
||||
Clear History:
|
||||
Clear History: Clear History
|
||||
# On Click
|
||||
Are you sure you want to delete your history?: Are you sure you want to delete
|
||||
your history?
|
||||
#& Yes
|
||||
#& No
|
||||
Clear Subscriptions:
|
||||
Clear Subscriptions: Clear Subscriptions
|
||||
# On Click
|
||||
Are you sure you want to remove all subscriptions?: Are you sure you want to
|
||||
remove all subscriptions?
|
||||
#& Yes
|
||||
#& No
|
||||
|
||||
Manage Subscriptions: Manage Subscriptions
|
||||
Proxy Settings:
|
||||
Proxy Settings: Proxy Settings
|
||||
Enable Tor / Proxy: Enable Tor / Proxy
|
||||
Proxy Protocol: Proxy Protocol
|
||||
Proxy Host: Proxy Host
|
||||
Proxy Port Number: Proxy Port Number
|
||||
Clicking on Test Proxy will send a request to: Clicking on Test Proxy will send a request to
|
||||
Test Proxy: Test Proxy
|
||||
Your Info: Your Info
|
||||
Ip: Ip
|
||||
Country: Country
|
||||
Region: Region
|
||||
City: City
|
||||
Error getting network information. Is your proxy configured properly?: Error getting network information. Is your proxy configured properly?
|
||||
About:
|
||||
#On About page
|
||||
About: About
|
||||
#& About
|
||||
'This software is FOSS and released under the GNU Affero General Public License v3.0.': This
|
||||
copylefted software is freely licensed AGPL-3.0.
|
||||
|
||||
'Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.': >-
|
||||
Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub
|
||||
page. Pull requests welcome.
|
||||
|
||||
Thank you very much to the People and Projects that make FreeTube possible!: Thank
|
||||
you very much to the People and Projects that make FreeTube possible!
|
||||
|
||||
'Want to chat? Join our Element / Matrix Server . Please check the rules before joining.': Want
|
||||
to chat? Join our Element / Matrix Server . Please check the rules before joining.
|
||||
|
||||
'Looking for help? Check out our Wiki page.': Looking for help? Check out our Wiki
|
||||
page.
|
||||
|
||||
Check out our Firefox extension!: Check out our Firefox extension!
|
||||
|
||||
'If you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin address.': If
|
||||
you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin
|
||||
address.
|
||||
|
||||
#~ 'BTC: 1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS'
|
||||
|
||||
Latest FreeTube News: Latest FreeTube News
|
||||
Beta: Beta
|
||||
Source code: Source code
|
||||
Licensed under the AGPLv3: Licensed under the AGPLv3
|
||||
View License: View License
|
||||
Downloads / Changelog: Downloads / Changelog
|
||||
GitHub releases: GitHub releases
|
||||
Help: Help
|
||||
FreeTube Wiki: FreeTube Wiki
|
||||
FAQ: FAQ
|
||||
Report a problem: Report a problem
|
||||
GitHub issues: GitHub issues
|
||||
Please check for duplicates before posting: Please check for duplicates before posting
|
||||
Website: Website
|
||||
Blog: Blog
|
||||
Email: Email
|
||||
Mastodon: Mastodon
|
||||
Chat on Matrix: Chat on Matrix
|
||||
Please read the: Please read the
|
||||
room rules: room rules
|
||||
Translate: Translate
|
||||
Credits: Credits
|
||||
FreeTube is made possible by: FreeTube is made possible by
|
||||
these people and projects: these people and projects
|
||||
Donate: Donate
|
||||
|
||||
Profile:
|
||||
Profile Select: Profile Select
|
||||
|
@ -388,6 +377,9 @@ Video:
|
|||
Remove From History: Remove From History
|
||||
Video has been marked as watched: Video has been marked as watched
|
||||
Video has been removed from your history: Video has been removed from your history
|
||||
Save Video: Save Video
|
||||
Video has been saved: Video has been saved
|
||||
Video has been removed from your saved list: Video has been removed from your saved list
|
||||
Open in YouTube: Open in YouTube
|
||||
Copy YouTube Link: Copy YouTube Link
|
||||
Open YouTube Embedded Player: Open YouTube Embedded Player
|
||||
|
|
|
@ -123,7 +123,7 @@ Settings:
|
|||
#! List countries
|
||||
Theme Settings:
|
||||
Theme Settings: 'Theme Settings'
|
||||
Match Top Bar with Main Color: 'Match Top Bar with Main Colour'
|
||||
Match Top Bar with Main Color: 'Match top bar with main colour'
|
||||
Base Theme:
|
||||
Base Theme: 'Base Theme'
|
||||
Black: 'Black'
|
||||
|
@ -246,7 +246,7 @@ Settings:
|
|||
'Proxy Address (Example: SOCKS5://127.0.0.1:9050 )': 'Proxy Address (Example:
|
||||
SOCKS5://127.0.0.1:9050 )'
|
||||
'Clicking "TEST PROXY" button will send a request to https://ipinfo.io/json': 'Clicking
|
||||
"TEST PROXY" button will send a request to https://ipinfo.io/json'
|
||||
‘TEST PROXY’ button will send a request to https://ipinfo.io/json'
|
||||
Use Tor / Proxy for API calls: 'Use Tor / Proxy for API calls'
|
||||
TEST PROXY: 'TEST PROXY'
|
||||
#& Invidious Instance (Default is https://invidious.snopyta.org)
|
||||
|
@ -275,39 +275,31 @@ Settings:
|
|||
Hide Channel Subscribers: Hide Channel Subscribers
|
||||
Hide Video Likes And Dislikes: Hide Video Likes And Dislikes
|
||||
Hide Video Views: Hide Video Views
|
||||
Hide Active Subscriptions: Hide Active Subscriptions
|
||||
Distraction Free Settings: Distraction Free Settings
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: The
|
||||
app needs to restart for changes to take effect. Do you want to restart and apply
|
||||
the changes?
|
||||
About:
|
||||
#On About page
|
||||
About: 'About'
|
||||
#& About
|
||||
'This software is FOSS and released under the GNU Affero General Public License v3.0.': 'This
|
||||
copylefted software is freely licenced AGPL-3.0.'
|
||||
|
||||
'Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.': >-
|
||||
Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub
|
||||
page. Pull requests welcome.
|
||||
|
||||
Thank you very much to the People and Projects that make FreeTube possible!: 'Thank
|
||||
you very much to the People and Projects that make FreeTube possible!'
|
||||
|
||||
'Want to chat? Join our Element / Matrix Server . Please check the rules before joining.': 'Want
|
||||
to chat? Join our Element / Matrix Server . Please check the rules before joining.'
|
||||
|
||||
'Looking for help? Check out our Wiki page.': 'Looking for help? Check out our Wiki
|
||||
page.'
|
||||
|
||||
Check out our Firefox extension!: 'Check out our Firefox extension!'
|
||||
|
||||
'If you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin address.': 'If
|
||||
you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin
|
||||
address.'
|
||||
|
||||
#~ 'BTC: 1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS'
|
||||
|
||||
Latest FreeTube News: 'Latest FreeTube News'
|
||||
About: About
|
||||
Contact: Contact
|
||||
Help: Help
|
||||
Useful Links: Useful Links
|
||||
Donate: Donate
|
||||
Beta: Beta
|
||||
License: License
|
||||
Email: Email
|
||||
Channel Rules: Channel Rules
|
||||
Report an Issue: Report an Issue
|
||||
Wiki: Wiki
|
||||
FAQ: FAQ
|
||||
Credits: Credits
|
||||
Blog: Blog
|
||||
Release Notes: Release Notes
|
||||
Source Code: Source Code
|
||||
Website: Website
|
||||
Translate via Weblate: Translate via Weblate
|
||||
|
||||
Profile:
|
||||
Profile Select: 'Profile Select'
|
||||
|
|
|
@ -270,6 +270,7 @@ Settings:
|
|||
Hide Comment Likes: No mostrar likes de comentarios
|
||||
Hide Channel Subscribers: No mostrar suscriptores en canales
|
||||
Distraction Free Settings: No distraer
|
||||
Hide Active Subscriptions: Ocultar suscripciones activas
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: ¿Quieres
|
||||
reiniciar FreeTube ahora para aplicar los cambios?
|
||||
About:
|
||||
|
|
|
@ -200,7 +200,7 @@ Settings:
|
|||
'Proxy Address (Example: SOCKS5://127.0.0.1:9050 )': 'Adresse Proxy (Exemple :
|
||||
SOCKS5://127.0.0.1:9050 )'
|
||||
'Clicking "TEST PROXY" button will send a request to https://ipinfo.io/json': 'Cliquer
|
||||
sur le bouton "TEST PROXY" enverra une demande à https://ipinfo.io/json'
|
||||
sur le bouton « TEST PROXY » enverra une demande à https://ipinfo.io/json'
|
||||
Use Tor / Proxy for API calls: 'Utiliser Tor / Proxy pour les appels de l''API'
|
||||
TEST PROXY: 'TESTER LE PROXY'
|
||||
#& Invidious Instance (Default is https://invidious.snopyta.org)
|
||||
|
@ -275,6 +275,7 @@ Settings:
|
|||
One or more subscriptions were unable to be imported: Un ou plusieurs abonnements
|
||||
n’ont pas pu être importés
|
||||
Check for Legacy Subscriptions: Vérifier les abonnements Legacy
|
||||
Manage Subscriptions: Gérer les abonnements
|
||||
Distraction Free Settings:
|
||||
Hide Video Likes And Dislikes: Masquer les J'aime et Je n'aime pas des vidéos
|
||||
Hide Comment Likes: Masquer les J'aime dans les commentaires
|
||||
|
@ -284,10 +285,28 @@ Settings:
|
|||
Hide Popular Videos: Masquer les vidéos populaires
|
||||
Hide Trending Videos: Masquer les tendances
|
||||
Hide Recommended Videos: Masquer les vidéos recommandées
|
||||
Distraction Free Settings: Mode Sans Distraction
|
||||
Distraction Free Settings: Mode sans distraction
|
||||
Hide Active Subscriptions: Masquer les abonnements actifs
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: L'application
|
||||
doit être redémarrée pour que les changements prennent effet. Redémarrer et appliquer
|
||||
les changements ?
|
||||
Proxy Settings:
|
||||
Error getting network information. Is your proxy configured properly?: Erreur
|
||||
lors de l'obtention des informations sur le réseau. Votre proxy est-il correctement
|
||||
configuré ?
|
||||
City: Ville
|
||||
Region: Région
|
||||
Country: Pays
|
||||
Ip: Ip
|
||||
Your Info: Vos informations
|
||||
Test Proxy: Test du Proxy
|
||||
Clicking on Test Proxy will send a request to: En cliquant sur Test Proxy, une
|
||||
demande sera envoyée à
|
||||
Proxy Port Number: Numéro de port du proxy
|
||||
Proxy Host: Hôte du proxy
|
||||
Proxy Protocol: Protocole du proxy
|
||||
Enable Tor / Proxy: Activer Tor / Proxy
|
||||
Proxy Settings: Paramètres du proxy
|
||||
About:
|
||||
#On About page
|
||||
About: 'À propos'
|
||||
|
@ -296,9 +315,9 @@ About:
|
|||
logiciel est sous licence AGPL-3.0.'
|
||||
|
||||
'Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.': >-
|
||||
Vous avez trouvé un bug ? Vous souhaitez suggérer une nouvelle fonctionnalité
|
||||
? Vous voulez aider de façon générale ? Rendez-vous sur la page GitHub. Les "Pull
|
||||
requests" sont les bienvenues.
|
||||
Vous avez trouvé une erreur ? Vous souhaitez suggérer une nouvelle fonctionnalité
|
||||
? Vous voulez aider de façon générale ? Rendez-vous sur la page GitHub. Les pull
|
||||
requests sont les bienvenues.
|
||||
|
||||
Thank you very much to the People and Projects that make FreeTube possible!: 'Un
|
||||
grand merci à toutes les personnes et à tous les projets qui ont rendu FreeTube
|
||||
|
@ -322,6 +341,30 @@ About:
|
|||
Latest FreeTube News: 'Les dernières actualités FreeTube'
|
||||
|
||||
#On Channel Page
|
||||
Channel Rules: Règles du salon
|
||||
Website: Site internet
|
||||
Source Code: Code source
|
||||
Release Notes: Notes de version
|
||||
Email: Courriel
|
||||
License: Licence
|
||||
Help: Aide
|
||||
Contact: Contacts
|
||||
Translate via Weblate: Traduire via Weblate
|
||||
Blog: Blog
|
||||
Credits: Crédits
|
||||
FAQ: FAQ
|
||||
Wiki: Wiki
|
||||
Report an Issue: Signaler un problème
|
||||
Beta: Bêta
|
||||
Donate: Faire un don
|
||||
Useful Links: Liens utiles
|
||||
Translate: Traduire
|
||||
Chat on Matrix: Chatter sur Matrix
|
||||
Mastodon: Mastodon
|
||||
Report a problem: Signaler un problème
|
||||
View License: Voir la license
|
||||
Licensed under the AGPLv3: Sous licence AGPLv3
|
||||
Source code: Code source
|
||||
Channel:
|
||||
Subscriber: 'Abonnement'
|
||||
Subscribers: 'Abonnements'
|
||||
|
|
|
@ -0,0 +1,602 @@
|
|||
# Put the name of your locale in the same language
|
||||
Locale Name: 'Galego'
|
||||
FreeTube: 'FreeTube'
|
||||
# Currently on Subscriptions, Playlists, and History
|
||||
'This part of the app is not ready yet. Come back later when progress has been made.': >-
|
||||
Esta parte da aplicación non está lista aínda. Volve máis adiante, cando se avance
|
||||
no desenvolvemento.
|
||||
|
||||
# Webkit Menu Bar
|
||||
File: 'Arquivo'
|
||||
Quit: 'Saír'
|
||||
Edit: 'Editar'
|
||||
Undo: 'Desfacer'
|
||||
Redo: 'Refacer'
|
||||
Cut: 'Cortar'
|
||||
Copy: 'Copiar'
|
||||
Paste: 'Pegar'
|
||||
Delete: 'Eliminar'
|
||||
Select all: 'Seleccionar todo'
|
||||
Reload: 'Recargar'
|
||||
Force Reload: 'Forzar recarga'
|
||||
Toggle Developer Tools: 'Activar Ferramentas de Desenvolvedor'
|
||||
Actual size: 'Tamaño real'
|
||||
Zoom in: 'Agrandar'
|
||||
Zoom out: 'Reducir'
|
||||
Toggle fullscreen: 'Activar pantalla completa'
|
||||
Window: 'Ventá'
|
||||
Minimize: 'Minimizar'
|
||||
Close: 'Pechar'
|
||||
Back: 'Atrás'
|
||||
Forward: 'Adiante'
|
||||
|
||||
Version $ is now available! Click for more details: 'A versión $ está dispoñible! Fai
|
||||
clic para veres máis detalles'
|
||||
Download From Site: 'Descargar do sitio web'
|
||||
A new blog is now available, $. Click to view more: 'Hai unha nova entrada no blog
|
||||
dispoñible, $. Fai clic para veres máis'
|
||||
|
||||
# Search Bar
|
||||
Search / Go to URL: 'Buscar / Ir á URL'
|
||||
# In Filter Button
|
||||
Search Filters:
|
||||
Search Filters: 'Buscar filtros'
|
||||
Sort By:
|
||||
Sort By: 'Clasificar por'
|
||||
Most Relevant: 'Máis relevante'
|
||||
Rating: 'Valoración'
|
||||
Upload Date: 'Data de subida'
|
||||
View Count: 'Visualizacións'
|
||||
Time:
|
||||
Time: 'Tempo'
|
||||
Any Time: 'Calquera momento'
|
||||
Last Hour: 'Última hora'
|
||||
Today: 'Hoxe'
|
||||
This Week: 'Esta semana'
|
||||
This Month: 'Este mes'
|
||||
This Year: 'Este ano'
|
||||
Type:
|
||||
Type: 'Tipo'
|
||||
All Types: 'Tódolos tipos'
|
||||
Videos: 'Vídeos'
|
||||
Channels: 'Canles'
|
||||
#& Playlists
|
||||
Duration:
|
||||
Duration: 'Duración'
|
||||
All Durations: 'Tódalas duracións'
|
||||
Short (< 4 minutes): 'Curta (< 4 minutos)'
|
||||
Long (> 20 minutes): 'Longa (> 20 minutos)'
|
||||
# On Search Page
|
||||
Search Results: 'Resultados da busca'
|
||||
Fetching results. Please wait: 'Buscando resultados. Por favor, agarda'
|
||||
Fetch more results: 'Buscar máis resultados'
|
||||
# Sidebar
|
||||
Subscriptions:
|
||||
# On Subscriptions Page
|
||||
Subscriptions: 'Subscricións'
|
||||
Latest Subscriptions: 'Últimas subscricións'
|
||||
This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: 'Este
|
||||
perfil ten unha gran cantidade de subscricións. Forzarase RSS para evitar o límite'
|
||||
'Your Subscription list is currently empty. Start adding subscriptions to see them here.': 'A
|
||||
túa listaxe de subscricións está baleira. Engade algunhas para as ver aquí.'
|
||||
'Getting Subscriptions. Please wait.': 'Obtendo subscricións. Por favor, agarda.'
|
||||
Refresh Subscriptions: 'Actualizar subscricións'
|
||||
Load More Videos: 'Cargar máis vídeos'
|
||||
Trending: 'Tendencias'
|
||||
Most Popular: 'Máis populares'
|
||||
Playlists: 'Listaxes de reprodución'
|
||||
User Playlists:
|
||||
Your Playlists: 'As túas listaxes de reprodución'
|
||||
History:
|
||||
# On History Page
|
||||
History: 'Histórico'
|
||||
Watch History: 'Histórico de visualizacións'
|
||||
Your history list is currently empty.: 'A túa listaxe histórica está baleira.'
|
||||
Settings:
|
||||
# On Settings Page
|
||||
Settings: 'Axustes'
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: 'Queres
|
||||
reiniciar a aplicación para aplicar os cambios?'
|
||||
General Settings:
|
||||
General Settings: 'Axustes xerais'
|
||||
Check for Updates: 'Comprobar actualizacións'
|
||||
Check for Latest Blog Posts: 'Comprobar se hai novas entradas no blog'
|
||||
Fallback to Non-Preferred Backend on Failure: 'Usar motor API non preferido en
|
||||
caso de falla'
|
||||
Enable Search Suggestions: 'Activar suxestións de busca'
|
||||
Default Landing Page: 'Páxina inicial'
|
||||
Locale Preference: 'Preferencia de localización'
|
||||
Preferred API Backend:
|
||||
Preferred API Backend: 'Motor API principal'
|
||||
Local API: 'API local'
|
||||
Invidious API: 'API de Invidious'
|
||||
Video View Type:
|
||||
Video View Type: 'Disposición dos vídeos'
|
||||
Grid: 'Grella'
|
||||
List: 'Listaxe'
|
||||
Thumbnail Preference:
|
||||
Thumbnail Preference: 'Preferencia de miniaturas'
|
||||
Default: 'Por defecto'
|
||||
Beginning: 'Principio'
|
||||
Middle: 'Metade'
|
||||
End: 'Final'
|
||||
'Invidious Instance (Default is https://invidious.snopyta.org)': 'Instancia de
|
||||
Invidious (por defecto é https://invidious.snopyta.org)'
|
||||
Region for Trending: 'Rexión para as tendencias'
|
||||
#! List countries
|
||||
Theme Settings:
|
||||
Theme Settings: 'Axustes de tema'
|
||||
Match Top Bar with Main Color: 'Combinar cor principal coa barra superior'
|
||||
Expand Side Bar by Default: 'Expandir barra lateral por defecto'
|
||||
Disable Smooth Scrolling: 'Desactivar desprazamento suavizado'
|
||||
UI Scale: 'Escala da interface'
|
||||
Base Theme:
|
||||
Base Theme: 'Tema base'
|
||||
Black: 'Negro'
|
||||
Dark: 'Escuro'
|
||||
Light: 'Claro'
|
||||
Main Color Theme:
|
||||
Main Color Theme: 'Cor principal'
|
||||
Red: 'Vermello'
|
||||
Pink: 'Rosa'
|
||||
Purple: 'Morado'
|
||||
Deep Purple: 'Morado escuro'
|
||||
Indigo: 'Índigo'
|
||||
Blue: 'Azul'
|
||||
Light Blue: 'Azul claro'
|
||||
Cyan: 'Ciano'
|
||||
Teal: 'Azul petróleo'
|
||||
Green: 'Verde'
|
||||
Light Green: 'Verde claro'
|
||||
Lime: 'Verde lima'
|
||||
Yellow: 'Amarelo'
|
||||
Amber: 'Ámbar'
|
||||
Orange: 'Laranxa'
|
||||
Deep Orange: 'Laranxa escuro'
|
||||
Secondary Color Theme: 'Cor secundaria'
|
||||
#* Main Color Theme
|
||||
Player Settings:
|
||||
Player Settings: 'Axustes do reprodutor'
|
||||
Force Local Backend for Legacy Formats: 'Forzar API local para formatos antigos
|
||||
(Legacy)'
|
||||
Play Next Video: 'Reproducir próximo vídeo'
|
||||
Turn on Subtitles by Default: 'Activar subtítulos por defecto'
|
||||
Autoplay Videos: 'Reproducir vídeos automaticamente'
|
||||
Proxy Videos Through Invidious: 'Utilizar Invidious como intermediario'
|
||||
Autoplay Playlists: 'Reproducir listaxes de reprodución automaticamente'
|
||||
Enable Theatre Mode by Default: 'Activar modo cinema por defecto'
|
||||
Default Volume: 'Volume predeterminado'
|
||||
Default Playback Rate: 'Velocidade de reprodución predeterminada'
|
||||
Default Video Format:
|
||||
Default Video Format: 'Formato de vídeo predeterminado'
|
||||
Dash Formats: 'Formato dash'
|
||||
Legacy Formats: 'Formato antigo (Legacy)'
|
||||
Audio Formats: 'Formato de audio'
|
||||
Default Quality:
|
||||
Default Quality: 'Calidade predeterminada'
|
||||
Auto: 'Automática'
|
||||
144p: '144p'
|
||||
240p: '240p'
|
||||
360p: '360p'
|
||||
480p: '480p'
|
||||
720p: '720p'
|
||||
1080p: '1080p'
|
||||
1440p: '1440p'
|
||||
4k: '4k'
|
||||
8k: '8k'
|
||||
Privacy Settings:
|
||||
Privacy Settings: 'Axustes de privacidade'
|
||||
Remember History: 'Lembrar histórico'
|
||||
Save Watched Progress: 'Gardar progreso da reprodución'
|
||||
Clear Search Cache: 'Limpar caché de busca'
|
||||
Are you sure you want to clear out your search cache?: 'Estás seguro de querer
|
||||
limpar o caché de busca?'
|
||||
Search cache has been cleared: 'Caché de busca limpado'
|
||||
Remove Watch History: 'Limpar histórico de reprodución'
|
||||
Are you sure you want to remove your entire watch history?: 'Estás seguro de querer
|
||||
limpar por completo o histórico de busca?'
|
||||
Watch history has been cleared: 'Histórico de busca limpado'
|
||||
Remove All Subscriptions / Profiles: 'Limpar tódalas subscricións / perfís'
|
||||
Are you sure you want to remove all subscriptions and profiles? This cannot be undone.: 'Estás
|
||||
seguro de querer limpar tódalas subscricións e perfís? Esta acción é irreversible.'
|
||||
Subscription Settings:
|
||||
Subscription Settings: 'Axustes de subscricións'
|
||||
Hide Videos on Watch: 'Agochar vídeos visualizados'
|
||||
Fetch Feeds from RSS: 'Obter subscricións através de RSS'
|
||||
Manage Subscriptions: 'Xestionar subscricións'
|
||||
Distraction Free Settings:
|
||||
Distraction Free Settings: 'Sen distraccións'
|
||||
Hide Video Views: 'Agochar as visualizacións nos vídeos'
|
||||
Hide Video Likes And Dislikes: 'Agochar likes/dislikes nos vídeos'
|
||||
Hide Channel Subscribers: 'Agochar subscritores nas canles'
|
||||
Hide Comment Likes: 'Agochar likes dos comentarios'
|
||||
Hide Recommended Videos: 'Agochar vídeos recomendados'
|
||||
Hide Trending Videos: 'Agochar vídeos en tendencias'
|
||||
Hide Popular Videos: 'Agochar vídeos populares'
|
||||
Hide Live Chat: 'Agochar chat en vivo'
|
||||
Data Settings:
|
||||
Data Settings: 'Axustes dos datos'
|
||||
Select Import Type: 'Escoller tipo de importación'
|
||||
Select Export Type: 'Escoller tipo de exportación'
|
||||
Import Subscriptions: 'Importar subscricións'
|
||||
Import FreeTube: 'Importar FreeTube'
|
||||
Import YouTube: 'Importar YouTube'
|
||||
Import NewPipe: 'Importar NewPipe'
|
||||
Check for Legacy Subscriptions: 'Comprobar subscricións antigas (Legacy)'
|
||||
Export Subscriptions: 'Exportar subscricións'
|
||||
Export FreeTube: 'Exportar Freetube'
|
||||
Export YouTube: 'Exportar YouTube'
|
||||
Export NewPipe: 'Exportar NewPipe'
|
||||
Import History: 'Importar histórico'
|
||||
Export History: 'Exportar histórico'
|
||||
Profile object has insufficient data, skipping item: 'Este perfil ten datos insuficientes,
|
||||
omitindo'
|
||||
All subscriptions and profiles have been successfully imported: 'Tódalas subscricións
|
||||
e perfís foron importados correctamente'
|
||||
All subscriptions have been successfully imported: 'Tódalas subscricións foron
|
||||
importadas correctamente'
|
||||
One or more subscriptions were unable to be imported: 'Unha ou máis subscricións
|
||||
non puideron ser importadas'
|
||||
Invalid subscriptions file: 'Ficheiro de subcricións inválido'
|
||||
This might take a while, please wait: 'Isto pode levar un cacho. Por favor, agarda'
|
||||
Invalid history file: 'Ficheiro de histórico inválido'
|
||||
Subscriptions have been successfully exported: 'As subscricións foron exportadas
|
||||
correctamente'
|
||||
History object has insufficient data, skipping item: 'O histórico ten datos insuficientes,
|
||||
omitindo'
|
||||
All watched history has been successfully imported: 'O histórico de visualizacións
|
||||
foi importado correctamente'
|
||||
All watched history has been successfully exported: 'O histórico de visualizacións
|
||||
foi exportado correctamente'
|
||||
Unable to read file: 'Imposible ler o ficheiro'
|
||||
Unable to write file: 'Imposible escribir o ficheiro'
|
||||
Unknown data key: 'Chave de datos descoñecida'
|
||||
How do I import my subscriptions?: 'Como podo importar as subscricións?'
|
||||
Advanced Settings:
|
||||
Advanced Settings: ''
|
||||
Enable Debug Mode (Prints data to the console): 'Activar modo de depuración (escribe
|
||||
datos na consola)'
|
||||
'Proxy Address (Example: SOCKS5://127.0.0.1:9050 )': 'Enderezo proxy (Exemplo:
|
||||
SOCKS5://127.0.0.1:9050 )'
|
||||
'Clicking "TEST PROXY" button will send a request to https://ipinfo.io/json': 'Premendo
|
||||
en "TESTAR PROXY" enviarase unha petición a https://ipinfo.io/json'
|
||||
Use Tor / Proxy for API calls: 'Usar Tor / Proxy para chamadas API'
|
||||
TEST PROXY: 'TESTAR PROXY'
|
||||
#& Invidious Instance (Default is https://invidious.snopyta.org)
|
||||
See Public Instances: 'Ver instancias públicas'
|
||||
Clear History:
|
||||
Clear History: 'Limpar histórico'
|
||||
# On Click
|
||||
Are you sure you want to delete your history?: 'Estás seguro de querer limpar
|
||||
o histórico?'
|
||||
#& Yes
|
||||
#& No
|
||||
Clear Subscriptions:
|
||||
Clear Subscriptions: 'Limpar subscricións'
|
||||
# On Click
|
||||
Are you sure you want to remove all subscriptions?: 'Estás seguro de querer
|
||||
limpar tódalas subscricións?'
|
||||
#& Yes
|
||||
#& No
|
||||
|
||||
About:
|
||||
#On About page
|
||||
About: 'Sobre'
|
||||
#& About
|
||||
'This software is FOSS and released under the GNU Affero General Public License v3.0.': 'Este
|
||||
software ten licencia libre AGPL-3.0.'
|
||||
|
||||
'Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.': >-
|
||||
Atopaches un erro? Tes algunha suxestión? Queres axudar? Visita a nosa páxina
|
||||
de GitHub. Calquera petición é benvida.
|
||||
|
||||
Thank you very much to the People and Projects that make FreeTube possible!: 'Moitas
|
||||
grazas a tódalas persoas e proxectos que fan FreeTube posible!'
|
||||
|
||||
'Want to chat? Join our Element / Matrix Server . Please check the rules before joining.': 'Queres
|
||||
chatear? Únete ao noso servidor Element / Matrix. Lembra comprobar as regras antes
|
||||
de te unir.'
|
||||
|
||||
'Looking for help? Check out our Wiki page.': 'Precisas axuda? Visita a nosa páxina
|
||||
Wiki.'
|
||||
|
||||
Check out our Firefox extension!: 'Comproba a nosa extensión para Firefox!'
|
||||
|
||||
'If you enjoy using FreeTube, consider donating via Liberapay or through our Bitcoin address.': 'Se
|
||||
estás a desfrutar FreeTube, considera doar através de Liberapay ou ao noso enderezo
|
||||
Bitcoin.'
|
||||
|
||||
#~ 'BTC: 1Lih7Ho5gnxb1CwPD4o59ss78pwo2T91eS'
|
||||
|
||||
Latest FreeTube News: 'Noticias recentes sobre FreeTube'
|
||||
|
||||
Profile:
|
||||
Profile Select: 'Selección de perfil'
|
||||
All Channels: 'Tódalas canles'
|
||||
Profile Manager: 'Xestor de perfís'
|
||||
Create New Profile: 'Crear novo perfil'
|
||||
Edit Profile: 'Editar perfil'
|
||||
Color Picker: 'Selector de cor'
|
||||
Custom Color: 'Cor personalizada'
|
||||
Profile Preview: 'Vista previa do perfil'
|
||||
Create Profile: 'Crear perfil'
|
||||
Update Profile: 'Actualizar perfil'
|
||||
Make Default Profile: 'Converter en perfil predeterminado'
|
||||
Delete Profile: 'Eliminar perfil'
|
||||
Are you sure you want to delete this profile?: 'Estás seguro de querer eliminar
|
||||
este perfil?'
|
||||
All subscriptions will also be deleted.: 'Tamén se eliminarán tódalas subscricións.'
|
||||
Profile could not be found: 'Non se atopou o perfil'
|
||||
Your profile name cannot be empty: 'O nome do perfil non pode estar en branco'
|
||||
Profile has been created: 'Creouse o perfil'
|
||||
Profile has been updated: 'Actualizouse o perfil'
|
||||
Your default profile has been set to $: '$ é agora o teu perfil predeterminado'
|
||||
Removed $ from your profiles: 'Eliminouse $ dos teus perfís'
|
||||
Your default profile has been changed to your primary profile: 'O teu perfil predeterminado
|
||||
cambiouse ao teu perfil primario'
|
||||
$ is now the active profile: '$ é agora o perfil activo'
|
||||
Subscription List: 'Listaxe de subcricións'
|
||||
Other Channels: 'Outras canles'
|
||||
$ selected: '$ seleccionado'
|
||||
Select All: 'Seleccionar todos'
|
||||
Select None: 'Non seleccionar ningún'
|
||||
Delete Selected: 'Eliminar seleccionados'
|
||||
Add Selected To Profile: 'Engadir seleccionados ao perfil'
|
||||
No channel(s) have been selected: 'Ningunha canle foi seleccionada'
|
||||
? This is your primary profile. Are you sure you want to delete the selected channels? The
|
||||
same channels will be deleted in any profile they are found in.
|
||||
: 'Este é o teu perfil principal. Estás seguro de querer eliminar as canles seleccionadas? Eliminaranse
|
||||
as mesmas en calquera perfil no que se atopen.'
|
||||
Are you sure you want to delete the selected channels? This will not delete the channel from any other profile.: 'Estás
|
||||
seguro de querer eliminar as canles seleccionadas? Esta acción non as eliminará
|
||||
de ningún outro perfil.'
|
||||
#On Channel Page
|
||||
Channel:
|
||||
Subscriber: 'Subscritor'
|
||||
Subscribers: 'Subscritores'
|
||||
Subscribe: 'Subscribirse'
|
||||
Unsubscribe: 'Desubscribirse'
|
||||
Channel has been removed from your subscriptions: 'Esta canle foi eliminada das
|
||||
túas subscricións'
|
||||
Removed subscription from $ other channel(s): ''
|
||||
Added channel to your subscriptions: 'Canle engadida ás túas subscricións'
|
||||
Search Channel: 'Buscar na canle'
|
||||
Your search results have returned 0 results: 'A busca non atopou resultados'
|
||||
Sort By: 'Ordenar por'
|
||||
Videos:
|
||||
Videos: 'Vídeos'
|
||||
This channel does not currently have any videos: 'Esta canle aínda non ten ningún
|
||||
vídeo'
|
||||
Sort Types:
|
||||
Newest: 'Máis recentes'
|
||||
Oldest: 'Máis antigos'
|
||||
Most Popular: 'Máis populares'
|
||||
Playlists:
|
||||
Playlists: 'Listaxes de reprodución'
|
||||
This channel does not currently have any playlists: 'Esta canle non ten ningunha
|
||||
listaxe de reprodución actualmente'
|
||||
Sort Types:
|
||||
Last Video Added: 'Último vídeo engadido'
|
||||
Newest: 'O máis recente'
|
||||
Oldest: 'O máis antigo'
|
||||
About:
|
||||
About: 'Sobre'
|
||||
Channel Description: 'Descrición da canle'
|
||||
Featured Channels: 'Canles destacadas'
|
||||
Video:
|
||||
Mark As Watched: 'Marcar como visto'
|
||||
Remove From History: 'Eliminar do histórico'
|
||||
Video has been marked as watched: 'O vídeo marcouse como visto'
|
||||
Video has been removed from your history: 'O vídeo eliminouse do teu histórico'
|
||||
Open in YouTube: 'Abrir no YouTube'
|
||||
Copy YouTube Link: 'Copiar ligazón de YouTube'
|
||||
Open YouTube Embedded Player: 'Abrir reprodutor integrado de YouTube'
|
||||
Copy YouTube Embedded Player Link: 'Copiar ligazón do preprodutor integrado de YouTube'
|
||||
Open in Invidious: 'Abrir no Invidious'
|
||||
Copy Invidious Link: 'Copiar ligazón de Invidious'
|
||||
Open Channel in YouTube: 'Abrir canle no YouTube'
|
||||
Copy YouTube Channel Link: 'Copiar ligazón de YouTube da canle'
|
||||
Open Channel in Invidious: 'Abrir canle no Invidious'
|
||||
Copy Invidious Channel Link: 'Copiar ligazón de Invidious da canle'
|
||||
View: ''
|
||||
Views: 'Visualizacións'
|
||||
Loop Playlist: 'Reprodución en bucle'
|
||||
Shuffle Playlist: 'Reprodución aleatoria'
|
||||
Reverse Playlist: 'Inverter listaxe de reprodución'
|
||||
Play Next Video: 'Reproducir próximo vídeo'
|
||||
Play Previous Video: 'Reproducir vídeo anterior'
|
||||
# Context is "X People Watching"
|
||||
Watching: 'A ver'
|
||||
Watched: 'Visto'
|
||||
Autoplay: 'Reprodución automática'
|
||||
Starting soon, please refresh the page to check again: 'Comezará en breve. Por favor,
|
||||
actualiza a páxina para verificares'
|
||||
# As in a Live Video
|
||||
Live: 'En vivo'
|
||||
Live Now: 'En vivo agora'
|
||||
Live Chat: 'Chat en vivo'
|
||||
Enable Live Chat: 'Activar chat en vivo'
|
||||
Live Chat is currently not supported in this build.: 'O chat en vivo non está soportado
|
||||
nesta versión.'
|
||||
'Chat is disabled or the Live Stream has ended.': 'O chat foi desactivado ou a transmisión
|
||||
en vivo rematou.'
|
||||
Live chat is enabled. Chat messages will appear here once sent.: 'Chat en vivo
|
||||
activado. As mensaxes aparecerán aquí ao seren enviadas.'
|
||||
'Live Chat is currently not supported with the Invidious API. A direct connection to YouTube is required.': 'Chat
|
||||
en vivo actualmente non soportado coa API de Invidious. Precísase dunha conexión
|
||||
directa con YouTube.'
|
||||
Download Video: 'Descargar vídeo'
|
||||
video only: 'Só vídeo'
|
||||
audio only: 'Só audio'
|
||||
Audio:
|
||||
Low: 'Baixa'
|
||||
Medium: 'Media'
|
||||
High: 'Alta'
|
||||
Best: 'Máxima'
|
||||
Published:
|
||||
Jan: 'Xan'
|
||||
Feb: 'Feb'
|
||||
Mar: 'Mar'
|
||||
Apr: 'Abr'
|
||||
May: 'Mai'
|
||||
Jun: 'Xuñ'
|
||||
Jul: 'Xul'
|
||||
Aug: 'Ago'
|
||||
Sep: 'Set'
|
||||
Oct: 'Out'
|
||||
Nov: 'Nov'
|
||||
Dec: 'Dec'
|
||||
Second: ''
|
||||
Seconds: 'Segundos'
|
||||
Minute: 'Minuto'
|
||||
Minutes: 'Minutos'
|
||||
Hour: 'Hora'
|
||||
Hours: 'Horas'
|
||||
Day: 'Día'
|
||||
Days: 'Días'
|
||||
Week: 'Semana'
|
||||
Weeks: 'Semanas'
|
||||
Month: 'Mes'
|
||||
Months: 'Meses'
|
||||
Year: 'Ano'
|
||||
Years: 'Anos'
|
||||
Ago: 'Hai'
|
||||
Upcoming: 'Estrea'
|
||||
Published on: 'Publicado'
|
||||
Streamed on: 'Transmitido'
|
||||
Started streaming on: 'A transmisión comezou'
|
||||
# $ is replaced with the number and % with the unit (days, hours, minutes...)
|
||||
Publicationtemplate: 'Hai $ %'
|
||||
#& Videos
|
||||
Videos:
|
||||
#& Sort By
|
||||
Sort By:
|
||||
Newest: 'Máis recente'
|
||||
Oldest: 'Máis antigo'
|
||||
#& Most Popular
|
||||
#& Playlists
|
||||
Playlist:
|
||||
#& About
|
||||
View Full Playlist: 'Ver listaxe de reprodución completa'
|
||||
Videos: 'Vídeos'
|
||||
View: 'Visualización'
|
||||
Views: 'Visualizacións'
|
||||
Last Updated On: 'Última actualización'
|
||||
Share Playlist:
|
||||
Share Playlist: 'Compartir listaxe de reprodución'
|
||||
Copy YouTube Link: 'Copiar ligazón de YouTube'
|
||||
Open in YouTube: 'Abrir no YouTube'
|
||||
Copy Invidious Link: 'Copiar ligazón de Invidious'
|
||||
Open in Invidious: 'Abrir en Invidious'
|
||||
|
||||
# On Video Watch Page
|
||||
#* Published
|
||||
#& Views
|
||||
Toggle Theatre Mode: 'Activar modo cinema'
|
||||
Change Format:
|
||||
Change Video Formats: 'Mudar formato do vídeo'
|
||||
Use Dash Formats: 'Utilizar formato Dash'
|
||||
Use Legacy Formats: 'Utilizar formato antigo (Legacy)'
|
||||
Use Audio Formats: 'Utilizar formato só de audio'
|
||||
Dash formats are not available for this video: 'Formato Dash non dispoñible para
|
||||
este vídeo'
|
||||
Audio formats are not available for this video: 'Formato só de audio non dispoñible
|
||||
para este vídeo'
|
||||
Share:
|
||||
Share Video: 'Compartir vídeo'
|
||||
Include Timestamp: 'Incluír marcación de tempo'
|
||||
Copy Link: 'Copiar ligazón'
|
||||
Open Link: 'Abrir ligazón'
|
||||
Copy Embed: 'Copiar código integrado'
|
||||
Open Embed: 'Abrir código integrado'
|
||||
# On Click
|
||||
Invidious URL copied to clipboard: 'Ligazón de Invidious copiada á área de transferencia'
|
||||
Invidious Embed URL copied to clipboard: 'Ligazón integrada de Invidious copiada
|
||||
á área de transferencia'
|
||||
Invidious Channel URL copied to clipboard: 'Ligazón de Invidious da canle copiada
|
||||
á área de transferencia'
|
||||
YouTube URL copied to clipboard: 'Ligazón de YouTube copiada á área de transferencia'
|
||||
YouTube Embed URL copied to clipboard: 'Ligazón integrada de YouTube copiada á área
|
||||
de transferencia'
|
||||
YouTube Channel URL copied to clipboard: 'Ligazón de YouTube da canle copiada á
|
||||
área de transferencia'
|
||||
|
||||
Mini Player: 'Mini-reprodutor'
|
||||
Comments:
|
||||
Comments: 'Comentarios'
|
||||
Click to View Comments: 'Premer para ver comentarios'
|
||||
Getting comment replies, please wait: 'Obtendo respostas ao comentario. Por favor,
|
||||
agarda'
|
||||
There are no more comments for this video: 'Non hai máis comentarios neste vídeo'
|
||||
Show Comments: 'Amosar comentarios'
|
||||
Hide Comments: 'Agochar comentarios'
|
||||
Sort by: 'Ordenar por'
|
||||
Top comments: 'Comentarios destacados'
|
||||
Newest first: 'Máis recentes'
|
||||
# Context: View 10 Replies, View 1 Reply
|
||||
View: 'Amosar'
|
||||
Hide: 'Agochar'
|
||||
Replies: 'Respostas'
|
||||
Reply: 'Resposta'
|
||||
There are no comments available for this video: 'Este vídeo non contén ningún comentario'
|
||||
Load More Comments: 'Cargar máis comentarios'
|
||||
No more comments available: 'Non hai máis comentarios'
|
||||
Up Next: 'Seguintes'
|
||||
|
||||
#Tooltips
|
||||
Tooltips:
|
||||
General Settings:
|
||||
Preferred API Backend: 'Escolle o back-end que FreeTube utiliza para obter os
|
||||
datos. A API local é un extractor incluído. A API de Invidious require un servidor
|
||||
Invidious ao que se conectar.'
|
||||
Fallback to Non-Preferred Backend on Failure: 'Cando a túa API primaria falla,
|
||||
FreeTube tentará utilizar a API secundaria automaticamente se se habilita'
|
||||
Thumbnail Preference: 'Tódalas miniaturas en FreeTube serán remplazadas cunha
|
||||
imaxe do vídeo no canto da miniatura predeterminada'
|
||||
Invidious Instance: 'A instancia de Invidious á que FreeTube se conectará para
|
||||
as chamadas API. Limpa a instancia actual para veres unha listaxe de instancias
|
||||
públicas'
|
||||
Region for Trending: 'A rexión das tendencias permíteche escoller os vídeos máis
|
||||
populares nun Estado. Non tódolos Estados que se amosan están soportados por
|
||||
YouTube'
|
||||
Player Settings:
|
||||
Force Local Backend for Legacy Formats: 'Só funcionará se a API de Invidious está
|
||||
escollida por defecto. Cando estea activa, a API local usará formatos antigos
|
||||
(Legacy) no canto dos de Invidious. Axuda cando Invidious non pode reproducir
|
||||
un vídeo por causa das restricións rexionais'
|
||||
Proxy Videos Through Invidious: 'Conectarase a Invidious para obter vídeos no
|
||||
canto de recorrer directamente a YouTube. Sobrescribirá a preferencia de API'
|
||||
Default Video Format: 'Selecciona os formatos usados cando se reproduce un vídeo.
|
||||
Os formatos Dash teñen resolucións máis altas. Os formatos antigos (Legacy)
|
||||
están limitados a 720p pero utilizan menos largura de banda. Os formatos de
|
||||
audio reproducen unicamente audio'
|
||||
Subscription Settings:
|
||||
Fetch Feeds from RSS: 'Cando está activado, FreeTube usará RSS no canto do método
|
||||
predeterminao para obter as subscricións. RSS é máis rápido e impide o bloqueo
|
||||
da IP, pero non proporciona certa información como a duración dun vídeo ou se
|
||||
é en vivo'
|
||||
|
||||
# Toast Messages
|
||||
Local API Error (Click to copy): 'Erro de API local (Preme para copiar)'
|
||||
Invidious API Error (Click to copy): 'Erro de API Invidious (Preme para copiar)'
|
||||
Falling back to Invidious API: 'Recorrendo á API Invidious'
|
||||
Falling back to the local API: 'Recorrendo á API local'
|
||||
This video is unavailable because of missing formats. This can happen due to country unavailability.: 'Este
|
||||
vídeo non está dispoñible por ter un formato inválido. Isto pode pasar pola non
|
||||
dispoñibilidade rexional'
|
||||
Subscriptions have not yet been implemented: 'As subscricións aínda non foron implementadas'
|
||||
Loop is now disabled: 'Reprodución en bucle desactivada'
|
||||
Loop is now enabled: 'Reprodución en bucle activada'
|
||||
Shuffle is now disabled: 'Reprodución aleatoria desactivada'
|
||||
Shuffle is now enabled: 'Reprodución aleatoria activada'
|
||||
The playlist has been reversed: 'A listaxe de reprodución foi invertida'
|
||||
Playing Next Video: 'A reproducir próximo vídeo'
|
||||
Playing Previous Video: 'A reproducir vídeo anterior'
|
||||
Playing next video in 5 seconds. Click to cancel: 'O próximo vídeo reproducirase
|
||||
en 5 segundos. Preme para cancelar.'
|
||||
Canceled next video autoplay: 'Reprodución cancelada'
|
||||
'The playlist has ended. Enable loop to continue playing': 'A listaxe de reprodución
|
||||
rematou. Activa a reprodución en bucle para continuar reproducindo'
|
||||
|
||||
Yes: 'Si'
|
||||
No: 'Non'
|
|
@ -86,6 +86,11 @@ Most Popular: 'הכי פופולרי'
|
|||
Playlists: 'פלייליסטים'
|
||||
User Playlists:
|
||||
Your Playlists: 'הפלייליסטים שלך'
|
||||
Playlist Message: העמוד הזה אינו משקף רשימות נגינה תקינות לחלוטין. הוא מציג רק סרטונים
|
||||
ששמרת או הוספת כמועדפים. עם סיום העבודה, כל הסרטונים שכאן ייובאו אל רשימת הנגינה
|
||||
‚מועדפים’.
|
||||
Your saved videos are empty. Click on the save button on the corner of a video to have it listed here: לא
|
||||
שמרת סרטונים. יש ללחוץ על כפתור השמירה בפינת הסרטון כדי שיופיע כאן
|
||||
History:
|
||||
# On History Page
|
||||
History: 'היסטוריה'
|
||||
|
@ -236,6 +241,7 @@ Settings:
|
|||
Unknown data key: 'מפתח נתון לא ידוע'
|
||||
How do I import my subscriptions?: 'איך לייבא את המנויים שלי?'
|
||||
Check for Legacy Subscriptions: איתור מינויים מיושנים
|
||||
Manage Subscriptions: ניהול מינויים
|
||||
Advanced Settings:
|
||||
Advanced Settings: 'הגדרות מתקדמות'
|
||||
Enable Debug Mode (Prints data to the console): 'הפעל מצב Debug ( מציג נתונים
|
||||
|
@ -273,8 +279,25 @@ Settings:
|
|||
Hide Video Likes And Dislikes: הסתרת לייקים ודיסלייקים לסרטון
|
||||
Distraction Free Settings: הגדרות להשבתת הסחות
|
||||
Hide Video Views: הסתרת תצוגות סרטונים
|
||||
Hide Active Subscriptions: הסתרת מינויים פעילים
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: צריך
|
||||
להפעיל את היישומון מחדש כדי שהשינויים ייכנסו לתוקף. להפעיל מחדש ולהחיל את השינוי?
|
||||
Proxy Settings:
|
||||
Error getting network information. Is your proxy configured properly?: קבלת פרטי
|
||||
הרשת נכשלה. המתווך שלך מוגדר כראוי?
|
||||
City: עיר
|
||||
Region: אזור
|
||||
Country: מדינה
|
||||
Ip: IP
|
||||
Your Info: הפרטים שלך
|
||||
Test Proxy: בדיקת המתווך
|
||||
Clicking on Test Proxy will send a request to: לחיצה על בדיקת המתווך תשלח בקשה
|
||||
אל
|
||||
Proxy Port Number: מספר פתחת מתווך
|
||||
Proxy Host: מארח מתווך
|
||||
Proxy Protocol: פרוטוקול מתווך
|
||||
Enable Tor / Proxy: הפעלת Tor / מתווך
|
||||
Proxy Settings: הגדרות מתווך
|
||||
About:
|
||||
#On About page
|
||||
About: 'על אודות'
|
||||
|
@ -304,6 +327,23 @@ About:
|
|||
|
||||
Latest FreeTube News: 'מה חדש ב-FreeTube'
|
||||
|
||||
Translate via Weblate: תרגום עם Weblate
|
||||
Website: אתר
|
||||
Source Code: קוד מקור
|
||||
Release Notes: הערות מהדורה
|
||||
Blog: בלוג
|
||||
Credits: תודות
|
||||
FAQ: שו״ת
|
||||
Wiki: ויקי
|
||||
Report an Issue: דיווח על תקלה
|
||||
Channel Rules: כללי הערוץ
|
||||
Email: דוא״ל
|
||||
License: רישיון
|
||||
Beta: בטא
|
||||
Donate: תרומה
|
||||
Useful Links: קישורים שימושיים
|
||||
Help: עזרה
|
||||
Contact: יצירת קשר
|
||||
Profile:
|
||||
Profile Select: 'בחירת פרופיל'
|
||||
All Channels: 'כל הערוצים'
|
||||
|
@ -456,6 +496,9 @@ Video:
|
|||
Open Channel in YouTube: פתיחת הערוץ ב־YouTube
|
||||
Started streaming on: ההזרמה החלה ב־
|
||||
Streamed on: הוזרם ב־
|
||||
Video has been removed from your saved list: הסרטון הוסר מרשימת השמורים שלך
|
||||
Video has been saved: סרטון נשמר
|
||||
Save Video: שמירת סרטון
|
||||
Videos:
|
||||
#& Sort By
|
||||
Sort By:
|
||||
|
|
|
@ -277,6 +277,7 @@ Settings:
|
|||
Hide Video Likes And Dislikes: Sakrij ocjenjivanje videa
|
||||
Hide Video Views: Sakrij broj gledanja videa
|
||||
Distraction Free Settings: Postavke za nesmetan rad
|
||||
Hide Active Subscriptions: Sakrij aktivne pretplate
|
||||
The app needs to restart for changes to take effect. Restart and apply change?: Za
|
||||
primjenu promjena, program se mora ponovo pokrenuti. Ponovo pokrenuti program?
|
||||
About:
|
||||
|
@ -310,6 +311,23 @@ About:
|
|||
|
||||
Latest FreeTube News: 'Najnovije vijesti o programu FreeTube'
|
||||
|
||||
Translate via Weblate: Prevedi putem Weblatea
|
||||
Website: Web-stranica
|
||||
Source Code: Izvorni kod
|
||||
Release Notes: Napomene uz izdanje
|
||||
Blog: Blog
|
||||
Credits: Zasluge
|
||||
FAQ: Često postavljena pitanja
|
||||
Wiki: Wiki
|
||||
Report an Issue: Prijavi problem
|
||||
Channel Rules: Pravila kanala
|
||||
Email: E-adresa
|
||||
License: Licenca
|
||||
Beta: Beta
|
||||
Donate: Doniraj
|
||||
Useful Links: Korisne poveznice
|
||||
Help: Pomoć
|
||||
Contact: Kontakt
|
||||
Profile:
|
||||
All Channels: 'Svi kanali'
|
||||
Profile Manager: 'Upravljač profila'
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue