Commit 99144731 authored by PrestonN's avatar PrestonN
Browse files

Merge branch 'development'

parents 597e2907 33876496
......@@ -40,6 +40,26 @@ to hide your IP while using FreeTube.
* Mini Player
* Light / dark theme
## Download Links
### Official Downloads
[GitHub Releases](https://github.com/FreeTubeApp/FreeTube/releases)
[FreeTube Website](https://freetubeapp.io/#download)
### 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/)
Chocolatey: [Download](https://chocolatey.org/packages/freetube/)
Windows Portable: [Download](https://github.com/rddim/FreeTubePortable/releases) [Source](https://github.com/rddim/FreeTubePortable)
## Contributing
If you have an idea or if you found a bug, please submit a GitHub issue so that
we can track it. Please search the existing issues before submitting to
......
{
"File": "Arquivo",
"Quit": "Sair",
"Edit": "Editar",
"Undo": "Desfazer",
"Redo": "Refazer",
"Cut": "Cortar",
"Copy": "Copiar",
"Paste": "Colar",
"Delete": "Apagar",
"Select all": "Selecionar tudo",
"View": "Ver",
"Reload": "Recarregar",
"Force Reload": "Forçar a recarregar",
"Toggle Developer Tools": "Ferramentas de Desenvolvimento de alternância",
"Actual size": "Tamanho atual",
"Zoom in": "Aumentar zoom",
"Zoom out": "Diminuir zoom",
"Toggle fullscreen": "Alternar para o modo tela cheia",
"Window": "Janela",
"Minimize": "Minimizar",
"Close": "Fechar",
"FreeTube": "FreeTube",
"Subscriptions": "Subscrições",
"Featured": "Em destaque",
"Most Popular": "Popular",
"Saved": "Salvou",
"Playlists": "Listas",
"History": "Histórico",
"Settings": "Configurações",
"About": "Sobre",
"Search / Go to URL": "Pesquisar / Ir para URL",
"Search Results": "Resultados",
"Subscriber": "Subscritor",
"Subscribers": "Subscritores",
"Video": "Vídeo",
"Videos": "Vídeos",
"View Full Playlist": "Ver Lista Completa",
"Live Now": "Ao Vivo",
"Fetch more results": "Buscar mais resultados",
"Fetching results. Please wait": "A buscar mais resultados. Por favor espere",
"Latest Subscriptions": "Subscrições recentes",
"Save Video": "Guardar vídeo",
"Remove Saved Video": "Remover vídeo guardado",
"Open in YouTube": "Abrir no Youtube",
"Copy YouTube Link": "Copiar link para Youtube",
"Open in HookTube": "Abrir no HookTube",
"Copy HookTube Link": "Copiar link para HookTube",
"URL has been copied to the clipboard": "O URL foi copiado",
"Found valid URL for 480p, but returned a 404. Video type might be available in the future.": "Foi encontrado um URL válido para 480p, mas devolveu um erro 404. Este tipo de vídeo pode estar disponível no futuro.",
"Save": "Salvar",
"Mini Player": "Mini Jogador",
"View": "Ver",
"Views": "Visualizacões",
"Subscribe": "Subscrever",
"Unsubscribe": "Cancelar subscrição",
"Published on": "Publicado em",
"Jan": "Jan",
"Feb": "Fev",
"Mar": "Mar",
"Apr": "Abr",
"May": "Mai",
"Jun": "Jun",
"Jul": "Jul",
"Aug": "Ago",
"Sep": "Set",
"Oct": "Out",
"Nov": "Nov",
"Dec": "Dez",
"Show Comments": "Mostrar comentários",
"Max of 100": "Máximo de 100",
"Recommendations": "Recomendado",
"Latest Subscriptions": "Subscrições recentes",
"Getting Subscriptions. Please wait...": "A buscar subscrições. Por favor espere...",
"Your Subscription list is currently empty. Start adding subscriptions to see them here.": "De momento não tens subscrições. Adiciona algumas para as ver aqui.",
"Saved Videos": "Vídeos guardados",
"Watch History": "Ver histórico",
"API Key": "Chave API",
"Set API Key: Leave blank to use default": "Definir chave API: Deixe em branco para usar padrão",
"Use Dark Theme": "Usar Tema Escuro",
"Import Subscriptions": "Importar Subscrições",
"Export Subscriptions": "Exportar Subcrições",
"Clear History": "Apagar Histórico",
"Are you sure you want to delete your history?": "Tens certeza que queres apagar o teu histórico?",
"Clear Saved Videos": "Apagar vídeos guardados",
"Are you sure you want to remove all saved videos?": "Tens a certeza que queres apagar todos os teus vídeos guardados?",
"Clear Subscriptions": "Cancelar Subscrições",
"Are you sure you want to remove all subscriptions?": "Tens a certeza que queres cancelar todas as tuas subscrições?",
"Save Settings": "Salvar configurações",
"Yes": "Sim",
"No": "Não",
"Beta": "Beta",
"This software is FOSS and released under the GNU Public License v3+.": "Este software é FOSS e lançado sobre a GPLv3+.",
"Found a bug? Want to suggest a feature? Want to help out? Check out our GitHub page. Pull requests are welcome.": "Encontraste um defeito? Queres fazer uma sugestão? Queres ajudar? Vê a nossa página no GitHub. Contribuições são agradecidas."
}
{
"name": "FreeTube",
"version": "0.5.1",
"version": "0.5.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -370,7 +370,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
"integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=",
"dev": true
"dev": true,
"optional": true
}
}
},
......@@ -1504,6 +1505,7 @@
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"dev": true,
"optional": true,
"requires": {
"hoek": "2.x.x"
}
......@@ -3253,7 +3255,8 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
"dev": true,
"optional": true
},
"jsonfile": {
"version": "4.0.0",
......@@ -3296,6 +3299,7 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
"optional": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
......@@ -3529,7 +3533,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"dev": true
"dev": true,
"optional": true
},
"fs-extra": {
"version": "2.1.2",
......@@ -4145,13 +4150,15 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
"dev": true
"dev": true,
"optional": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^1.9.0"
}
......@@ -4161,6 +4168,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
......@@ -4172,6 +4180,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"optional": true,
"requires": {
"color-name": "1.1.3"
}
......@@ -4251,6 +4260,7 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^3.0.0"
}
......@@ -4260,6 +4270,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^3.0.0"
}
......@@ -5400,7 +5411,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz",
"integrity": "sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk=",
"dev": true
"dev": true,
"optional": true
},
"indent-string": {
"version": "2.1.0",
......@@ -5639,7 +5651,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=",
"dev": true
"dev": true,
"optional": true
},
"is-relative-path": {
"version": "1.0.2",
......@@ -6561,11 +6574,19 @@
}
},
"m3u8stream": {
"version": "0.2.2",
"resolved": "http://registry.npmjs.org/m3u8stream/-/m3u8stream-0.2.2.tgz",
"integrity": "sha512-R/xWLXBtVr0m9sPruRL4p9uO01JyHxhcQ4nhqQhVgyT802OZyVW+dn+fWHvTnbfE6YMLc65TksZZut+Mh2OVMQ==",
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.6.2.tgz",
"integrity": "sha512-WsuM2bd5pPN80xvfrB+1DZqr4M7+kJl8byi6+ZCy6cmVjEiHhmr/desN53Ngsa6Hs13kYumeVgT4wL0oIJ+v6g==",
"requires": {
"miniget": "^1.1.0"
"miniget": "^1.4.0",
"sax": "^1.2.4"
},
"dependencies": {
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
}
}
},
"macos-alias": {
......@@ -6658,9 +6679,9 @@
"dev": true
},
"miniget": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/miniget/-/miniget-1.5.0.tgz",
"integrity": "sha512-RbRCj2m8Q/arS1nExuMB8qO4QavCpvfetQR+HVCeHGiFJGOryPn8u0z4WrIx9AAIDYFDVcFhQsRYvSY+UA5HJQ=="
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/miniget/-/miniget-1.5.1.tgz",
"integrity": "sha512-KJ3AyIVZ76QuWAq43BWjkK+jLdhxhy3s4tsdg9Je91+cIFkeOSW2VEj2lSeKw50CPu1eCCkSbiQEBKL36mpA5w=="
},
"minimatch": {
"version": "3.0.4",
......@@ -6773,7 +6794,8 @@
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
"integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
"dev": true
"dev": true,
"optional": true
},
"natives": {
"version": "1.1.6",
......@@ -8211,7 +8233,8 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
"dev": true,
"optional": true
},
"rx-lite-aggregates": {
"version": "4.0.8",
......@@ -9795,13 +9818,13 @@
}
},
"ytdl-core": {
"version": "0.20.4",
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-0.20.4.tgz",
"integrity": "sha512-d+jthiJxSQ6yqCeCwwMggXYOjFSOJsD7ahvAAE1sFW9nVNnsA/roz91SFH1FzaMGS7/y7AnJfhVgpE9i8uYjJQ==",
"version": "0.29.1",
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-0.29.1.tgz",
"integrity": "sha512-J/TW3rupqE6y+TczHTTFjuwf23tweA9fasmnbU/5yYH0O2IRFLcwgHbbvEPt3t8mtXWGX207+TWH7uuJpB1FKQ==",
"requires": {
"html-entities": "^1.1.3",
"m3u8stream": "^0.2.1",
"miniget": "^1.1.0",
"m3u8stream": "^0.6.2",
"miniget": "^1.4.0",
"sax": "^1.1.3"
}
},
......
{
"name": "FreeTube",
"productName": "FreeTube",
"version": "0.5.1",
"version": "0.5.2",
"description": "An Open Source YouTube app for privacy.",
"main": "src/js/init.js",
"scripts": {
......@@ -94,7 +94,6 @@
"electron-compile": "6.4.2",
"electron-context-menu": "^0.10.0",
"electron-squirrel-startup": "^1.0.0",
"github-version-checker": "^2.0.1",
"jquery": "^3.3.1",
"jsdom": "^11.11.0",
"mustache": "^2.3.0",
......
......@@ -256,24 +256,23 @@ $(document).on('click', '#confirmNo', hideConfirmFunction);
// Open links externally by default
$(document).on('click', 'a[href^="http"]', (event) => {
let el = event.currentTarget;
if (!el.href.includes('freetube')) {
if (!el.href.includes('freetube://')) {
event.preventDefault();
shell.openExternal(el.href);
}
else{
window.open(el.href,"_self");
search(el.href);
}
});
// Open links externally on middle click.
$(document).on('auxclick', 'a[href^="http"]', (event) => {
let el = event.currentTarget;
if (!el.href.includes('freetube')) {
if (!el.href.includes('freetube://')) {
event.preventDefault();
shell.openExternal(el.href);
}
else{
event.preventDefault();
let url = el.href.replace('freetube://', '');
shell.openExternal(el.href);
search(el.href);
}
});
......@@ -58,11 +58,13 @@ function addToHistory(data){
*
* @return {Void}
*/
function removeFromHistory(videoId){
function removeFromHistory(videoId, toast = true){
const data = {videoId: videoId};
historyDb.remove(data, {}, (err, numRemoved) => {
if (!err) {
showToast('Video removed from history');
if (toast) {
if (!err) {
showToast('Video removed from history');
}
}
});
}
......@@ -106,7 +108,7 @@ function showHistory(){
videoData.position = index;
displayVideo(videoData, 'history');
}, () => {
removeFromHistory(video.videoId);
removeFromHistory(video.videoId, false);
});
}
else{
......
......@@ -38,7 +38,9 @@ let win;
protocol.registerStandardSchemes(['freetube']);
app.setAsDefaultProtocolClient('freetube');
app.setAsDefaultProtocolClient('freetube');//--autoplay-policy=no-user-gesture-required
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
......@@ -167,7 +169,7 @@ let init = function () {
/**
* Sets proxy when setProxy event is sent from renderer
*
*
* example data "SOCKS5://127.0.0.1:9050"
*/
ipcMain.on("setProxy", (_e, data) => {
......
......@@ -52,8 +52,11 @@ require.extensions['.html'] = function (module, filename) {
electron.ipcRenderer.on('ping', function(event, message) {
console.log(message);
let url = message[1].replace('freetube://', '');
parseSearchText(url);
let url = message[message.length-1];
if (url) {
url = url.replace('freetube://', '');
parseSearchText(url);
}
ft.log(message);
});
......
This diff is collapsed.
......@@ -70,11 +70,16 @@ function addSavedVideo(videoId) {
*
* @return {Void}
*/
function removeSavedVideo(videoId, string) {
function removeSavedVideo(videoId, toast = true) {
savedVidsDb.remove({
videoId: videoId
}, {}, (err, numRemoved) => {
showToast('Video has been removed from the favorites list.');
if (toast) {
showToast('Video has been removed from the favorites list.');
}
if (savedView.seen === true) {
showSavedVideos();
}
});
}
......@@ -166,7 +171,7 @@ function showSavedVideos() {
videoData.position = index;
displayVideo(videoData, 'saved');
}, () => {
removeSavedVideo(video.videoId);
removeSavedVideo(video.videoId, false);
});
}
else {
......
......@@ -165,12 +165,7 @@ function checkDefaultSettings() {
checkForUpdates = docs[0]['value'];
if (checkForUpdates) {
updateChecker(options, function (error, update) { // callback function
if (error) throw error;
if (update) { // print some update info if an update is available
confirmFunction(update.name + ' is now available! Would you like to download the update?', openReleasePage);
}
});
checkForNewUpdate();
}
break;
case 'quality':
......@@ -591,12 +586,56 @@ function exportSubscriptions() {
const dateYear = date.getFullYear();
const dateString = 'freetube-subscriptions-' + dateYear + '-' + dateMonth + '-' + dateDay;
// Open user file browser. User gives location of file to be created.
switch(document.querySelector('#exportSelect').value){
case "NewPipe":
exportNewpipeSubscriptions(dateYear, dateMonth, dateDay);
break;
case "OPML":
exportOpmlSubscriptions(dateYear, dateMonth, dateDay);
break;
default:
// Open user file browser. User gives location of file to be created.
dialog.showSaveDialog({
defaultPath: dateString,
filters: [{
name: 'Database File',
extensions: ['db']
}, ]
}, function(fileLocation) {
console.log(fileLocation);
if (typeof(fileLocation) === 'undefined') {
console.log('Export Aborted');
return;
}
fs.readFile(appDatabaseFile, function(readErr, data) {
if (readErr) {
throw readErr;
}
fs.writeFile(fileLocation, data, function(writeErr) {
if (writeErr) {
throw writeErr;
}
showToast('Susbcriptions have been successfully exported');
});
})
});
}
}
/**
* Export the subscriptions database compatable with NewPipe.
*
* @return {Void}
*/
function exportNewpipeSubscriptions(dateYear, dateMonth, dateDay){
const dateString = 'newpipe-subscriptions-' + dateYear + '-' + dateMonth + '-' + dateDay;
dialog.showSaveDialog({
defaultPath: dateString,
filters: [{
name: 'Database File',
extensions: ['db']
name: 'JSON',
extensions: ['json']
}, ]
}, function(fileLocation) {
console.log(fileLocation);
......@@ -604,20 +643,81 @@ function exportSubscriptions() {
console.log('Export Aborted');
return;
}
fs.readFile(appDatabaseFile, function(readErr, data) {
if (readErr) {
throw readErr;
}
fs.writeFile(fileLocation, data, function(writeErr) {
if (writeErr) {
throw writeErr;
returnSubscriptions().then((result)=>{
let newpipe = {
app_version: "0.16.1",
app_version_int: 730,
subscriptions: []
}
showToast('Susbcriptions have been successfully exported');
});
})
for (let i=0; i < result.length; i++) {
let subs = {
service_id: 0,
url: `https://youtube.com/channel/${result[i].channelId}`,
name: result[i].channelName
}
newpipe.subscriptions.push(subs);
fs.writeFile(fileLocation, JSON.stringify(newpipe), function(writeErr) {
if (writeErr) {
throw writeErr;
}
if (i === result.length-1) {
showToast('Susbcriptions have been successfully exported');
return;
}
});
}
});
});
}
/**
* Export subscriptions database as OPML.
*
* @return {Void}
*/
function exportOpmlSubscriptions(dateYear, dateMonth, dateDay){
const dateString = 'freetube-subscriptions-' + dateYear + '-' + dateMonth + '-' + dateDay;
dialog.showSaveDialog({
defaultPath: dateString,
filters: [{
name: 'OPML',
extensions: ['opml']
}, ]
}, function(fileLocation) {
console.log(fileLocation);
if (typeof(fileLocation) === 'undefined') {
console.log('Export Aborted');
return;
}
returnSubscriptions().then((result)=>{
let opml = `<opml version="1.1"><body><outline text="YouTube Subscriptions" title="YouTube Subscriptions">`;
for (let i=0; i < result.length; i++) {
let subs = `<outline text="${result[i].channelName}" title="${result[i].channelName}" type="rss" xmlUrl="https://www.youtube.com/feeds/videos.xml?channel_id=${result[i].channelId}"/>`;
if (i === result.length-1) {
subs += `</outline></body></opml>`;
}
opml += subs;
fs.writeFile(fileLocation, opml, function(writeErr) {
if (writeErr) {
throw writeErr;
}
if (i === result.length-1) {
showToast('Susbcriptions have been successfully exported');
return;
}
});
}
});
});