From 13567ad4aff99e7af9af303d5e409de8cf7896e2 Mon Sep 17 00:00:00 2001 From: K06RA Date: Tue, 24 Jul 2018 01:11:56 +0000 Subject: [PATCH] Huge Code Clean up and Small Issue Fixes * Added ability for div.video to change size. This is needed because it fixes the issue of not being able to see the new menus later on when we might need to add more menus to the context menu. I also deleted display: inline block because it won't work since there's a float: right (always enforces display: block). * Removed display: inline-block * Converted from Typescript to JS... Even if this was supposed to be for Vue, there's no Vue module installed on this branch... * Added .code-workspace in .gitignore for those who use a vscode workspace. Also added .jsbeautifyrc to clean up the code. This is definitely a good idea when the project gets larger. * Formatted the entire codebase to use a single coding standard. * Added comment header to all files * Some things actually weren't formatted correctly, so I fixed those * Code fixup * Forgot to change API key * Fixed issue #136 * Fixed ft.logs --- .compilerc | 4 +- .gitignore | 1 + .jsbeautifyrc | 49 ++ package-lock.json | 398 ++++++++++--- package.json | 194 +++--- src/index.html | 129 ++-- src/js/channels.js | 124 ++-- src/js/events.js | 345 ++++++----- src/js/general.js | 39 ++ src/js/history.js | 142 ++--- src/js/init.js | 218 ++++--- src/js/layout.js | 265 +++++---- src/js/models/comment.model.js | 34 +- src/js/models/commentThread.model.js | 40 +- src/js/player.js | 610 ++++++++++--------- src/js/savedVideos.js | 258 ++++---- src/js/settings.js | 635 ++++++++++---------- src/js/subscriptions.js | 326 +++++------ src/js/updates.js | 60 +- src/js/videos.js | 843 ++++++++++++++------------- src/js/youtubeApi.js | 99 ++-- src/style/channel.css | 81 ++- src/style/darkTheme.css | 281 +++++++-- src/style/lightTheme.css | 219 +++++-- src/style/loading.css | 78 ++- src/style/main.css | 472 ++++++++------- src/style/player.css | 384 ++++++------ src/style/videoList.css | 6 +- src/templates/about.html | 35 +- src/templates/channelList.html | 29 +- src/templates/channelView.html | 35 +- src/templates/comments.html | 39 +- src/templates/miniPlayer.html | 77 ++- src/templates/player.html | 144 +++-- src/templates/playerWindow.html | 164 +++--- src/templates/playlistList.html | 31 +- src/templates/recommendations.html | 31 +- src/templates/settings.html | 71 ++- src/templates/subscriptions.html | 21 +- src/templates/video.html | 20 +- src/templates/videoList.html | 57 +- 41 files changed, 4053 insertions(+), 3035 deletions(-) create mode 100644 .jsbeautifyrc create mode 100644 src/js/general.js diff --git a/.compilerc b/.compilerc index 6c1a6c295..fb9429932 100644 --- a/.compilerc +++ b/.compilerc @@ -3,7 +3,7 @@ "development": { "application/javascript": { "presets": [ - ["env", { "targets": { "electron": "1.4" } }], + ["env", { "targets": { "electron-renderer": "1.4" } }], "react" ], "plugins": ["transform-async-to-generator"], @@ -13,7 +13,7 @@ "production": { "application/javascript": { "presets": [ - ["env", { "targets": { "electron": "1.4" } }], + ["env", { "targets": { "electron-renderer": "1.4" } }], "react" ], "plugins": ["transform-async-to-generator"], diff --git a/.gitignore b/.gitignore index 2ec91a4da..5c067f640 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ subscriptions\.db .vscode/ .eslintrc* *.db +*.code-workspace electron-packager/win32-x64/FreeTube-win32-x64/ diff --git a/.jsbeautifyrc b/.jsbeautifyrc new file mode 100644 index 000000000..9de93e7b0 --- /dev/null +++ b/.jsbeautifyrc @@ -0,0 +1,49 @@ +{ + "html": { + "allowed_file_extensions": ["htm", "html", "xhtml", "shtml", "xml", "svg", "dust"], + "brace_style": "collapse", + "end_with_newline": true, + "indent_char": " ", + "indent_handlebars": true, + "indent_inner_html": false, + "indent_scripts": "keep", + "indent_size": 4, + "max_preserve_newlines": 10, + "preserve_newlines": true, + "unformatted": ["a", "span", "img", "code", "pre", "sub", "sup", "em", "strong", "b", "i", "u", "strike", "big", "small", "pre", "h1", "h2", "h3", "h4", "h5", "h6"], // List of tags that should not be reformatted + "wrap_line_length": 0 + }, + "css": { + "allowed_file_extensions": ["css", "scss", "sass", "less"], + "end_with_newline": true, + "indent_char": " ", + "indent_size": 4, + "newline_between_rules": true, + "selector_separator": " ", + "selector_separator_newline": true, + "preserve_newlines": true, + "max_preserve_newlines": 10 + }, + "js": { + "allowed_file_extensions": ["js", "json", "jshintrc", "jsbeautifyrc"], + "brace_style": "collapse", + "break_chained_methods": false, + "e4x": false, + "end_with_newline": false, + "indent_char": " ", + "indent_level": 0, + "indent_size": 4, + "indent_with_tabs": false, + "jslint_happy": true, + "keep_array_indentation": false, + "keep_function_indentation": false, + "max_preserve_newlines": 0, + "preserve_newlines": true, + "space_after_anon_function": true, + "space_before_conditional": true, + "space_in_empty_paren": false, + "space_in_paren": false, + "unescape_strings": false, + "wrap_line_length": 0 + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index da071de35..467f17890 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "FreeTube", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -78,9 +78,7 @@ "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "dev": true, - "optional": true + "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=" }, "abbrev": { "version": "1.1.1", @@ -163,6 +161,11 @@ "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, + "ansi-font": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ansi-font/-/ansi-font-0.0.2.tgz", + "integrity": "sha1-iQMBvVhBRi/TnAt3Ca/R9SUUMzE=" + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -355,6 +358,11 @@ "sprintf-js": "~1.0.2" } }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -418,6 +426,11 @@ "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1347,6 +1360,11 @@ "concat-map": "0.0.1" } }, + "browser-process-hrtime": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", + "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=" + }, "browserslist": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", @@ -1712,6 +1730,63 @@ "htmlparser2": "~3.8.1", "jsdom": "^7.0.2", "lodash": "^4.1.0" + }, + "dependencies": { + "cssstyle": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", + "dev": true, + "optional": true, + "requires": { + "cssom": "0.3.x" + } + }, + "jsdom": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", + "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", + "dev": true, + "optional": true, + "requires": { + "abab": "^1.0.0", + "acorn": "^2.4.0", + "acorn-globals": "^1.0.4", + "cssom": ">= 0.3.0 < 0.4.0", + "cssstyle": ">= 0.2.29 < 0.3.0", + "escodegen": "^1.6.1", + "nwmatcher": ">= 1.3.7 < 2.0.0", + "parse5": "^1.5.1", + "request": "^2.55.0", + "sax": "^1.1.4", + "symbol-tree": ">= 3.1.0 < 4.0.0", + "tough-cookie": "^2.2.0", + "webidl-conversions": "^2.0.0", + "whatwg-url-compat": "~0.6.5", + "xml-name-validator": ">= 2.0.1 < 3.0.0" + } + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "dev": true, + "optional": true + }, + "webidl-conversions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", + "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", + "dev": true, + "optional": true + }, + "xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "dev": true, + "optional": true + } } }, "chromium-pickle-js": { @@ -1901,6 +1976,15 @@ "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", "dev": true }, + "commonjs": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/commonjs/-/commonjs-0.0.1.tgz", + "integrity": "sha1-ZcUx3P9lZcp8ld38lmIricwClNU=", + "requires": { + "system": ">=0.0.1", + "test": ">=0.0.5" + } + }, "compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -2193,17 +2277,14 @@ } }, "cssom": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", - "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=", - "dev": true + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" }, "cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "dev": true, - "optional": true, + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.3.1.tgz", + "integrity": "sha512-tNvaxM5blOnxanyxI6panOsnfiyLRj3HV4qjqqS45WPNS1usdYWRUQjqTEEELK73lpeP/1KoIGYUwrBn/VcECA==", "requires": { "cssom": "0.3.x" } @@ -2230,6 +2311,16 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz", + "integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==", + "requires": { + "abab": "^1.0.4", + "whatwg-mimetype": "^2.0.0", + "whatwg-url": "^6.4.0" + } + }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -2277,8 +2368,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "defaults": { "version": "1.0.3", @@ -2417,6 +2507,14 @@ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", "dev": true }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "domhandler": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", @@ -4225,11 +4323,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", - "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", - "dev": true, - "optional": true, + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -4241,15 +4337,12 @@ "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true, - "optional": true + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "optional": true } } @@ -4262,15 +4355,12 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true, - "optional": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "events": { "version": "1.1.1", @@ -4382,8 +4472,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fd-slicer": { "version": "1.0.1", @@ -5054,6 +5143,14 @@ "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", @@ -5642,27 +5739,56 @@ "optional": true }, "jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "dev": true, - "optional": true, + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.11.0.tgz", + "integrity": "sha512-ou1VyfjwsSuWkudGxb03FotDajxAto6USAlmMZjE2lc0jCznt7sBWkhfRBRaWwbnmDqdMSTKTLT5d9sBFkkM7A==", "requires": { - "abab": "^1.0.0", - "acorn": "^2.4.0", - "acorn-globals": "^1.0.4", - "cssom": ">= 0.3.0 < 0.4.0", - "cssstyle": ">= 0.2.29 < 0.3.0", - "escodegen": "^1.6.1", - "nwmatcher": ">= 1.3.7 < 2.0.0", - "parse5": "^1.5.1", - "request": "^2.55.0", - "sax": "^1.1.4", - "symbol-tree": ">= 3.1.0 < 4.0.0", - "tough-cookie": "^2.2.0", - "webidl-conversions": "^2.0.0", - "whatwg-url-compat": "~0.6.5", - "xml-name-validator": ">= 2.0.1 < 3.0.0" + "abab": "^1.0.4", + "acorn": "^5.3.0", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": ">= 0.3.1 < 0.4.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.0", + "escodegen": "^1.9.0", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.2.0", + "nwsapi": "^2.0.0", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.83.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.3", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^4.0.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==" + }, + "acorn-globals": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", + "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", + "requires": { + "acorn": "^5.0.0" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + } } }, "jsesc": { @@ -5817,6 +5943,11 @@ "invert-kv": "^1.0.0" } }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, "less": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", @@ -6005,7 +6136,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -6060,8 +6190,7 @@ "lodash": { "version": "4.17.10", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -6135,6 +6264,11 @@ "integrity": "sha1-YAYMxr1iW01FZ+wn3EXNG+nuwBI=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -6619,6 +6753,11 @@ "dev": true, "optional": true }, + "nwsapi": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.7.tgz", + "integrity": "sha512-VZXniaaaORAXGCNsvUNefsKRQYk8zCzQZ57jalgrpHcU70OrAzKAiN/3plYtH/VPRmZeYyUzQiYfKzcMXC1g5Q==" + }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", @@ -6706,7 +6845,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -6885,11 +7023,9 @@ "dev": true }, "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "dev": true, - "optional": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" }, "parser-toolkit": { "version": "0.0.5", @@ -6986,6 +7122,11 @@ } } }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", @@ -7301,8 +7442,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "1.0.4", @@ -7683,6 +7823,24 @@ "uuid": "^3.1.0" } }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "^4.13.1" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8147,6 +8305,11 @@ "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", "dev": true }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, "stream-json": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-0.6.1.tgz", @@ -8368,9 +8531,7 @@ "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", - "dev": true, - "optional": true + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" }, "synchronous-promise": { "version": "1.0.18", @@ -8378,6 +8539,11 @@ "integrity": "sha512-UqMAK6BBBXu8qaDI5omlyV9iDpM9nQfgthaBOK0nlfXnMgiuOBv+meWG73CGeCCFRhOOOa2e4rvqYzfynzy5zg==", "dev": true }, + "system": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/system/-/system-2.0.1.tgz", + "integrity": "sha512-BwSUSa8LMHZouGadZ34ck3TsrH5s3oMmTKPK+xHdbBnTCZOZMJ38fHGKLAHkBl0PXru1Z4BsymQU4qqvTxWzdQ==" + }, "tabtab": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-2.2.2.tgz", @@ -8596,6 +8762,14 @@ "lazy-val": "^1.0.3" } }, + "test": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/test/-/test-0.6.0.tgz", + "integrity": "sha1-WYasRF7Bd1QyJRLRBLoyyKY+k44=", + "requires": { + "ansi-font": "0.0.2" + } + }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", @@ -8759,11 +8933,19 @@ } }, "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true, - "optional": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } }, "transformers": { "version": "2.1.0", @@ -8865,7 +9047,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -9102,6 +9283,14 @@ "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==", "dev": true }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -9112,11 +9301,39 @@ } }, "webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "dev": true, - "optional": true + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz", + "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==", + "requires": { + "iconv-lite": "0.4.19" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + } + } + }, + "whatwg-mimetype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", + "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } }, "whatwg-url-compat": { "version": "0.6.5", @@ -9126,6 +9343,15 @@ "optional": true, "requires": { "tr46": "~0.0.1" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true, + "optional": true + } } }, "whet.extend": { @@ -9190,8 +9416,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { "version": "2.1.0", @@ -9214,12 +9439,19 @@ "dev": true, "optional": true }, + "ws": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0" + } + }, "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", - "dev": true, - "optional": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, "xml2js": { "version": "0.4.17", diff --git a/package.json b/package.json index bf7f4f8de..8be3b9835 100644 --- a/package.json +++ b/package.json @@ -1,100 +1,102 @@ { - "name": "FreeTube", - "productName": "FreeTube", - "version": "0.3.1", - "description": "An Open Source YouTube app for privacy.", - "main": "src/js/init.js", - "scripts": { - "start": "electron-forge start", - "package": "electron-forge package", - "make": "electron-forge make", - "publish": "electron-forge publish", - "make:all": "npm run make:mac && npm run make:linux:x86 && npm run make:linux:arm && npm run make:win", - "make:mac": "electron-forge make --platform=darwin", - "make:win": "electron-forge make --platform=win32", - "make:win:zip": "electron-forge make --platform=win32 --targets=zip", - "make:linux:x86": "electron-forge make --platform=linux --arch x64", - "make:linux:x86:zip": "electron-forge make --platform=linux --targets=zip --arch x64", - "make:linux:x86:deb": "electron-forge make --platform=linux --targets=deb --arch x64", - "make:linux:x86:rpm": "electron-forge make --platform=linux --targets=rpm --arch x64", - "make:linux:x86:snap": "electron-forge package && electron-installer-snap --src=out/FreeTube-linux-x64 --arch x64", - "make:linux:x86:flatpak": "electron-installer-flatpak --src out/FreeTube-linux-x64/ --dest out/make --arch x64", - "make:linux:x86:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch x64", - "make:linux:arm": "electron-forge make --platform=linux --arch arm64", - "make:linux:arm:zip": "electron-forge make --platform=linux --targets=zip --arch arm64", - "make:linux:arm:deb": "electron-forge make --platform=linux --targets=deb --arch arm64", - "make:linux:arm:rpm": "electron-forge make --platform=linux --targets=rpm --arch arm64", - "make:linux:arm:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch arm64" - }, - "keywords": [], - "author": { - "name": "PrestonN", - "email": "FreeTubeApp@protonmail.com", - "url": "https://github.com/FreeTubeApp/FreeTube" - }, - "license": "GPL-3.0-or-later", - "config": { - "forge": { - "make_targets": { - "win32": [ - "squirrel" - ], - "darwin": [ - "zip" - ], - "linux": [ - "deb", - "rpm", - "electron-forge-maker-appimage", - "zip" - ] - }, - "protocols": [ - { - "name": "freetube", - "role": "Viewer", - "schemes": [ - "freetube" - ] - } - ], - "electronPackagerConfig": { - "packageManager": "yarn", - "icon": "./src/icons/iconColor.icns" - }, - "electronWinstallerConfig": { - "name": "freetube", - "iconUrl": "https://raw.githubusercontent.com/FreeTubeApp/FreeTubeApp.github.io/master/images/iconColor.ico", - "setupIcon": "./src/icons/iconColor.ico" - }, - "electronInstallerDebian": { - "icon": "src/icons/iconColor.png" - }, - "repository": { - "type": "git", + "name": "FreeTube", + "productName": "FreeTube", + "version": "0.3.1", + "description": "An Open Source YouTube app for privacy.", + "main": "src/js/init.js", + "scripts": { + "start": "electron-forge start", + "package": "electron-forge package", + "make": "electron-forge make", + "publish": "electron-forge publish", + "make:all": "npm run make:mac && npm run make:linux:x86 && npm run make:linux:arm && npm run make:win", + "make:mac": "electron-forge make --platform=darwin", + "make:win": "electron-forge make --platform=win32", + "make:win:zip": "electron-forge make --platform=win32 --targets=zip", + "make:linux:x86": "electron-forge make --platform=linux --arch x64", + "make:linux:x86:zip": "electron-forge make --platform=linux --targets=zip --arch x64", + "make:linux:x86:deb": "electron-forge make --platform=linux --targets=deb --arch x64", + "make:linux:x86:rpm": "electron-forge make --platform=linux --targets=rpm --arch x64", + "make:linux:x86:snap": "electron-forge package && electron-installer-snap --src=out/FreeTube-linux-x64 --arch x64", + "make:linux:x86:flatpak": "electron-installer-flatpak --src out/FreeTube-linux-x64/ --dest out/make --arch x64", + "make:linux:x86:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch x64", + "make:linux:arm": "electron-forge make --platform=linux --arch arm64", + "make:linux:arm:zip": "electron-forge make --platform=linux --targets=zip --arch arm64", + "make:linux:arm:deb": "electron-forge make --platform=linux --targets=deb --arch arm64", + "make:linux:arm:rpm": "electron-forge make --platform=linux --targets=rpm --arch arm64", + "make:linux:arm:appimage": "electron-forge make --platform=linux --targets=electron-forge-maker-appimage --arch arm64" + }, + "keywords": [], + "author": { + "name": "PrestonN", + "email": "FreeTubeApp@protonmail.com", "url": "https://github.com/FreeTubeApp/FreeTube" - } + }, + "license": "GPL-3.0-or-later", + "config": { + "forge": { + "make_targets": { + "win32": [ + "squirrel" + ], + "darwin": [ + "zip" + ], + "linux": [ + "deb", + "rpm", + "electron-forge-maker-appimage", + "zip" + ] + }, + "protocols": [ + { + "name": "freetube", + "role": "Viewer", + "schemes": [ + "freetube" + ] + } + ], + "electronPackagerConfig": { + "packageManager": "yarn", + "icon": "./src/icons/iconColor.icns" + }, + "electronWinstallerConfig": { + "name": "freetube", + "iconUrl": "https://raw.githubusercontent.com/FreeTubeApp/FreeTubeApp.github.io/master/images/iconColor.ico", + "setupIcon": "./src/icons/iconColor.ico" + }, + "electronInstallerDebian": { + "icon": "src/icons/iconColor.png" + }, + "repository": { + "type": "git", + "url": "https://github.com/FreeTubeApp/FreeTube" + } + } + }, + "devDependencies": { + "electron-forge": "^5.2.2", + "electron-forge-maker-appimage": "^20.14.4", + "electron-installer-flatpak": "^0.8.0", + "electron-installer-snap": "^2.0.1", + "electron-prebuilt-compile": "2.0.2", + "electron-winstaller": "^2.6.4" + }, + "dependencies": { + "autolinker": "^1.6.2", + "commonjs": "0.0.1", + "dateformat": "^3.0.3", + "electron-compile": "6.4.2", + "electron-squirrel-startup": "^1.0.0", + "github-version-checker": "^2.0.1", + "jquery": "^3.3.1", + "jsdom": "^11.11.0", + "mustache": "^2.3.0", + "nedb": "^1.8.0", + "opml-to-json": "0.0.3", + "tor-request": "^2.1.2", + "ytdl-core": "^0.20.4" } - }, - "devDependencies": { - "electron-forge": "^5.2.2", - "electron-forge-maker-appimage": "^20.14.4", - "electron-installer-flatpak": "^0.8.0", - "electron-installer-snap": "^2.0.1", - "electron-prebuilt-compile": "2.0.2", - "electron-winstaller": "^2.6.4" - }, - "dependencies": { - "autolinker": "^1.6.2", - "dateformat": "^3.0.3", - "electron-compile": "6.4.2", - "electron-squirrel-startup": "^1.0.0", - "github-version-checker": "^2.0.1", - "jquery": "^3.3.1", - "mustache": "^2.3.0", - "nedb": "^1.8.0", - "opml-to-json": "0.0.3", - "tor-request": "^2.1.2", - "ytdl-core": "^0.20.4" - } } diff --git a/src/index.html b/src/index.html index 2b6e3187a..e10fbf8fc 100644 --- a/src/index.html +++ b/src/index.html @@ -2,76 +2,77 @@ - - - - - - - - - - - - - - - - - - - - - Freetube Player + + + + + + + + + + + + + + + + + + + + + + + Freetube Player -
-
-
-
+
+
+
+
+
-
-
- Would you like to perform the function? -
Yes
-
No
-
-
- - -
-
- - -
-
-
-
    -
  •   Subscriptions
  • -
  •   Most Popular
  • -
  •   Saved
  • -
  •   History
  • -
-
-
    -
  •   Settings
  • -
  •   About
  • -
-
-
    -
+
+ + +
+
+ + +   + +
+
+
+
+
    +
  •   Subscriptions
  • +
  •   Most Popular
  • +
  •   Favorites
  • +
  •   History
  • +
+
+
    +
  •   Settings
  • +
  •   About
  • +
+
+
    +
+
+
+
-
-
-
diff --git a/src/js/channels.js b/src/js/channels.js index b4e88ec05..5705eabf6 100644 --- a/src/js/channels.js +++ b/src/js/channels.js @@ -1,25 +1,25 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ /* -* File for all functions related specifically for channels. -*/ + * File for all functions related specifically for channels. + */ /*function getChannelThumbnail(channelId, callback) { let url = ''; @@ -33,60 +33,60 @@ along with FreeTube. If not, see . }*/ /** -* Display a channel page, showing latest uploads. -* -* @param {string} channelId - The channel ID to display. -* -* @return {Void} -*/ + * Display a channel page, showing latest uploads. + * + * @param {string} channelId - The channel ID to display. + * + * @return {Void} + */ function goToChannel(channelId) { - event.stopPropagation(); - clearMainContainer(); - startLoadingAnimation(); + event.stopPropagation(); + clearMainContainer(); + startLoadingAnimation(); - let subButtonText; - // Setting subButtonText here as Mustache templates are logic-less. - isSubscribed(channelId).then((subscribed) => { - subButtonText = (subscribed ? "UNSUBSCRIBE" : "SUBSCRIBE"); - }); - - // Grab general channel information - youtubeAPI('channels', { - part: 'snippet,brandingSettings,statistics', - id: channelId, - }, function (data){ - const channelData = data.items[0]; - - const channelViewTemplate = require('./templates/channelView.html'); - mustache.parse(channelViewTemplate); - const rendered = mustache.render(channelViewTemplate, { - channelId: channelId, - channelName: channelData.brandingSettings.channel.title, - channelBanner: channelData.brandingSettings.image.bannerImageUrl, - channelImage: channelData.snippet.thumbnails.high.url, - subCount: channelData.statistics.subscriberCount.toLocaleString(), //toLocaleString adds commas as thousands separators - channelDescription: autolinker.link(channelData.brandingSettings.channel.description), //autolinker makes URLs clickable - subButtonText: subButtonText, + let subButtonText; + // Setting subButtonText here as Mustache templates are logic-less. + isSubscribed(channelId).then((subscribed) => { + subButtonText = (subscribed ? "UNSUBSCRIBE" : "SUBSCRIBE"); }); - $('#main').html(rendered); - stopLoadingAnimation(); - // Grab the channel's latest uploads. API forces a max of 50. - youtubeAPI('search', { - part: 'snippet', - channelId: channelId, - type: 'video', - maxResults: 50, - order: 'date', + // Grab general channel information + youtubeAPI('channels', { + part: 'snippet,brandingSettings,statistics', + id: channelId, }, function (data) { - // Display recent uploads to #main - let grabDuration = getDuration(data.items); + const channelData = data.items[0]; - grabDuration.then((videoList) => { - videoList.items.forEach((video) => { - displayVideo(video); + const channelViewTemplate = require('./templates/channelView.html'); + mustache.parse(channelViewTemplate); + const rendered = mustache.render(channelViewTemplate, { + channelId: channelId, + channelName: channelData.brandingSettings.channel.title, + channelBanner: channelData.brandingSettings.image.bannerImageUrl, + channelImage: channelData.snippet.thumbnails.high.url, + subCount: channelData.statistics.subscriberCount.toLocaleString(), //toLocaleString adds commas as thousands separators + channelDescription: autolinker.link(channelData.brandingSettings.channel.description), //autolinker makes URLs clickable + subButtonText: subButtonText, + }); + $('#main').html(rendered); + stopLoadingAnimation(); + + // Grab the channel's latest uploads. API forces a max of 50. + youtubeAPI('search', { + part: 'snippet', + channelId: channelId, + type: 'video', + maxResults: 50, + order: 'date', + }, function (data) { + // Display recent uploads to #main + let grabDuration = getDuration(data.items); + + grabDuration.then((videoList) => { + videoList.items.forEach((video) => { + displayVideo(video); + }); + }); }); - }); }); - }); -} +} \ No newline at end of file diff --git a/src/js/events.js b/src/js/events.js index ae5fd4e69..8f3adb3c7 100644 --- a/src/js/events.js +++ b/src/js/events.js @@ -1,22 +1,20 @@ - /* -This file is part of FreeTube. +/* + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + sit under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ - - /* * File for events within application. Work needs to be done throughout the application * to use this style more. Please use this style going forward if possible. @@ -26,185 +24,179 @@ along with FreeTube. If not, see . * Event when user clicks comment box, * and wants to show/display comments for the user. */ -let showComments = function(event) { - let comments = $('#comments'); +let showComments = function (event) { + let comments = $('#comments'); - if (comments.css('display') === 'none') { - comments.attr('loaded', 'true'); + if (comments.css('display') === 'none') { + comments.attr('loaded', 'true'); - youtubeAPI('commentThreads', { - 'videoId': $('#comments').attr('data-video-id'), - 'part': 'snippet,replies', - 'maxResults': 100, - }, function (data){ - let comments = []; - let items = data.items; + youtubeAPI('commentThreads', { + 'videoId': $('#comments').attr('data-video-id'), + 'part': 'snippet,replies', + 'maxResults': 100, + }, function (data) { + let comments = []; + let items = data.items; - items.forEach((object) => { - let snippet = object.snippet.topLevelComment.snippet; + items.forEach((object) => { + let snippet = object.snippet.topLevelComment.snippet; - snippet.publishedAt = dateFormat(new Date(snippet.publishedAt), "mmm dS, yyyy"); + snippet.publishedAt = dateFormat(new Date(snippet.publishedAt), "mmm dS, yyyy"); - comments.push(snippet); - }) - const commentsTemplate = require('./templates/comments.html'); - const html = mustache.render(commentsTemplate, { - comments: comments, - }); - $('#comments').html(html); - }); + comments.push(snippet); + }) + const commentsTemplate = require('./templates/comments.html'); + const html = mustache.render(commentsTemplate, { + comments: comments, + }); + $('#comments').html(html); + }); - comments.show(); - } else { - comments.hide(); - } + comments.show(); + } else { + comments.hide(); + } }; /** * Play / Pause the video player upon click. */ -let playPauseVideo = function(event) { - let el = event.currentTarget; - el.paused ? el.play() : el.pause(); +let playPauseVideo = function (event) { + let el = event.currentTarget; + el.paused ? el.play() : el.pause(); }; -$('.videoPlayer').keypress((event) => { - console.log(event.which); -}); -let videoShortcutHandler = function(event) { - console.log(event.which); - let videoPlayer = $('.videoPlayer').get(0); - if (typeof(videoPlayer) !== 'undefined' && !$('#jumpToInput').is(':focus') && !$('#search').is(':focus')){ - switch (event.which) { - case 32: - // Space Bar - event.preventDefault(); - videoPlayer.paused ? videoPlayer.play() : videoPlayer.pause(); - break; - case 74: - // J Key - event.preventDefault(); - changeDurationBySeconds(-10); - break; - case 75: - // K Key - event.preventDefault(); - videoPlayer.paused ? videoPlayer.play() : videoPlayer.pause(); - break; - case 76: - // L Key - event.preventDefault(); - changeDurationBySeconds(10); - break; - case 70: - // F Key - event.preventDefault(); - videoPlayer.webkitRequestFullscreen(); - break; - case 77: - // M Key - event.preventDefault(); - let volume = videoPlayer.volume; - console.log(volume); - if (volume > 0){ - changeVolume(-1); +let videoShortcutHandler = function (event) { + + let videoPlayer = $('.videoPlayer').get(0); + if (typeof (videoPlayer) !== 'undefined' && !$('#jumpToInput').is(':focus') && !$('#search').is(':focus')) { + switch (event.which) { + case 32: + // Space Bar + event.preventDefault(); + videoPlayer.paused ? videoPlayer.play() : videoPlayer.pause(); + break; + case 74: + // J Key + event.preventDefault(); + changeDurationBySeconds(-10); + break; + case 75: + // K Key + event.preventDefault(); + videoPlayer.paused ? videoPlayer.play() : videoPlayer.pause(); + break; + case 76: + // L Key + event.preventDefault(); + changeDurationBySeconds(10); + break; + case 70: + // F Key + event.preventDefault(); + videoPlayer.webkitRequestFullscreen(); + break; + case 77: + // M Key + event.preventDefault(); + let volume = videoPlayer.volume; + + if (volume > 0) { + changeVolume(-1); + } else { + changeVolume(1); + } + break; + case 67: + // C Key + let subtitleMode = $('.videoPlayer').get(0).textTracks[0].mode; + if (subtitleMode === 'hidden') { + $('.videoPlayer').get(0).textTracks[0].mode = 'showing' + } else { + $('.videoPlayer').get(0).textTracks[0].mode = 'hidden' + } + break; + case 38: + // Up Arrow Key + event.preventDefault(); + changeVolume(0.05); + break; + case 40: + // Down Arrow Key + event.preventDefault(); + changeVolume(-0.05); + break; + case 37: + // Left Arrow Key + event.preventDefault(); + changeDurationBySeconds(-5); + break; + case 39: + // Right Arrow Key + event.preventDefault(); + changeDurationBySeconds(5); + break; + case 49: + // 1 Key + event.preventDefault(); + changeDurationByPercentage(0.1); + break; + case 50: + // 2 Key + event.preventDefault(); + changeDurationByPercentage(0.2); + break; + case 51: + // 3 Key + event.preventDefault(); + changeDurationByPercentage(0.3); + break; + case 52: + // 4 Key + event.preventDefault(); + changeDurationByPercentage(0.4); + break; + case 53: + // 5 Key + event.preventDefault(); + changeDurationByPercentage(0.5); + break; + case 54: + // 6 Key + event.preventDefault(); + changeDurationByPercentage(0.6); + break; + case 55: + // 7 Key + event.preventDefault(); + changeDurationByPercentage(0.7); + break; + case 56: + // 8 Key + event.preventDefault(); + changeDurationByPercentage(0.8); + break; + case 57: + // 9 Key + event.preventDefault(); + changeDurationByPercentage(0.9); + break; + case 48: + // 0 Key + event.preventDefault(); + changeDurationByPercentage(0); + break; } - else{ - changeVolume(1); - } - break; - case 67: - // C Key - let subtitleMode = $('.videoPlayer').get(0).textTracks[0].mode; - if (subtitleMode === 'hidden'){ - $('.videoPlayer').get(0).textTracks[0].mode = 'showing' - } - else{ - $('.videoPlayer').get(0).textTracks[0].mode = 'hidden' - } - break; - case 38: - // Up Arrow Key - event.preventDefault(); - changeVolume(0.05); - break; - case 40: - // Down Arrow Key - event.preventDefault(); - changeVolume(-0.05); - break; - case 37: - // Left Arrow Key - event.preventDefault(); - changeDurationBySeconds(-5); - break; - case 39: - // Right Arrow Key - event.preventDefault(); - changeDurationBySeconds(5); - break; - case 49: - // 1 Key - event.preventDefault(); - changeDurationByPercentage(0.1); - break; - case 50: - // 2 Key - event.preventDefault(); - changeDurationByPercentage(0.2); - break; - case 51: - // 3 Key - event.preventDefault(); - changeDurationByPercentage(0.3); - break; - case 52: - // 4 Key - event.preventDefault(); - changeDurationByPercentage(0.4); - break; - case 53: - // 5 Key - event.preventDefault(); - changeDurationByPercentage(0.5); - break; - case 54: - // 6 Key - event.preventDefault(); - changeDurationByPercentage(0.6); - break; - case 55: - // 7 Key - event.preventDefault(); - changeDurationByPercentage(0.7); - break; - case 56: - // 8 Key - event.preventDefault(); - changeDurationByPercentage(0.8); - break; - case 57: - // 9 Key - event.preventDefault(); - changeDurationByPercentage(0.9); - break; - case 48: - // 0 Key - event.preventDefault(); - changeDurationByPercentage(0); - break; } - } }; -let fullscreenVideo = function(event){ - if (document.webkitFullscreenElement !== null){ - document.webkitExitFullscreen(); - } - else{ - $('.videoPlayer').get(0).webkitRequestFullscreen(); - } +let fullscreenVideo = function (event) { + if (document.webkitFullscreenElement !== null) { + document.webkitExitFullscreen(); + } else { + $('.videoPlayer').get(0).webkitRequestFullscreen(); + } } /** @@ -212,6 +204,7 @@ let fullscreenVideo = function(event){ * Bind click events * -------------------------- */ + $(document).on('click', '#showComments', showComments); $(document).on('click', '.videoPlayer', playPauseVideo); @@ -220,4 +213,4 @@ $(document).on('dblclick', '.videoPlayer', fullscreenVideo); $(document).on('keydown', videoShortcutHandler); -$(document).on('click', '#confirmNo', hideConfirmFunction); +$(document).on('click', '#confirmNo', hideConfirmFunction); \ No newline at end of file diff --git a/src/js/general.js b/src/js/general.js new file mode 100644 index 000000000..d8fa6cebb --- /dev/null +++ b/src/js/general.js @@ -0,0 +1,39 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + +let ft = {}; + +/** + * + * Use this function instead of console.log. + * This function logs the date, time and presents the information in a readable format + * + * @param {*} data + * + * @returns {Void} + */ +ft.log = function (...data) { + let currentTime = new Date(); + let time = currentTime.getDate() + "/" + + (currentTime.getMonth() + 1) + "/" + + currentTime.getFullYear() + "@" + + currentTime.getHours() + ":" + + currentTime.getMinutes() + ":" + + currentTime.getSeconds(); + + console.log('[' + time + '] ' + '[FREETUBE]', data); +} \ No newline at end of file diff --git a/src/js/history.js b/src/js/history.js index 0b8636afd..b7307c14f 100644 --- a/src/js/history.js +++ b/src/js/history.js @@ -1,94 +1,94 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ /* -* File used for functions related to video history. -*/ + * File used for functions related to video history. + */ /** -* Add a video to the history database file -* -* @param {string} videoId - The video ID of the video to be saved. -* -* @return {Void} -*/ -function addToHistory(videoId){ - const data = { - videoId: videoId, - timeWatched: new Date().getTime(), - }; - historyDb.insert(data, (err, newDoc) => {}); + * Add a video to the history database file + * + * @param {string} videoId - The video ID of the video to be saved. + * + * @return {Void} + */ +function addToHistory(videoId) { + const data = { + videoId: videoId, + timeWatched: new Date().getTime(), + }; + historyDb.insert(data, (err, newDoc) => {}); } /** -* Remove a video from the history database file -* -* @param {string} videoId - The video ID of the video to be removed. -* -* @return {Void} -*/ -function removeFromHistory(videoId){ - const data = {videoId: videoId}; - historyDb.remove(data, {}, (err, numRemoved) => {}); + * Remove a video from the history database file + * + * @param {string} videoId - The video ID of the video to be removed. + * + * @return {Void} + */ +function removeFromHistory(videoId) { + const data = { + videoId: videoId + }; + historyDb.remove(data, {}, (err, numRemoved) => {}); } /** -* Show the videos within the history database. -* -* @return {Void} -*/ -function showHistory(){ - clearMainContainer(); - startLoadingAnimation(); - console.log('checking history'); + * Show the videos within the history database. + * + * @return {Void} + */ +function showHistory() { + clearMainContainer(); + startLoadingAnimation(); - let videoList = ''; + let videoList = ''; - historyDb.find({}).sort({ - timeWatched: -1 - }).exec((err, docs) => { - if(docs.length > 49){ - // The YouTube API limits the search to 50 videos, so grab 50 most recent. - for (let i = 0; i < 49; i++) { - videoList = videoList + ',' + docs[i]['videoId']; - } - } - else{ - docs.forEach((video) => { - videoList = videoList + ',' + video['videoId']; - }); - } + historyDb.find({}).sort({ + timeWatched: -1 + }).exec((err, docs) => { + if (docs.length > 49) { + // The YouTube API limits the search to 50 videos, so grab 50 most recent. + for (let i = 0; i < 49; i++) { + videoList = videoList + ',' + docs[i]['videoId']; + } + } else { + docs.forEach((video) => { + videoList = videoList + ',' + video['videoId']; + }); + } - youtubeAPI('videos', { - part: 'snippet', - id: videoList, - maxResults: 50, - }, function (data) { - createVideoListContainer('Watch History:'); - let grabDuration = getDuration(data.items); + youtubeAPI('videos', { + part: 'snippet', + id: videoList, + maxResults: 50, + }, function (data) { + createVideoListContainer('Watch History:'); + let grabDuration = getDuration(data.items); - grabDuration.then((videoList) => { - videoList.items.forEach((video) => { - displayVideo(video, 'history'); + grabDuration.then((videoList) => { + videoList.items.forEach((video) => { + displayVideo(video, 'history'); + }); + }); + stopLoadingAnimation() }); - }); - stopLoadingAnimation() }); - }); -} +} \ No newline at end of file diff --git a/src/js/init.js b/src/js/init.js index 2be8daaa9..aa8ae5417 100644 --- a/src/js/init.js +++ b/src/js/init.js @@ -1,28 +1,34 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ /* -* File used to initializing the application -*/ -const {app, BrowserWindow, dialog, protocol} = require('electron'); + * File used to initializing the application + */ +const { + app, + BrowserWindow, + dialog, + protocol +} = require('electron'); const path = require('path'); const url = require('url'); + let win; protocol.registerStandardSchemes(['freetube']); @@ -30,103 +36,141 @@ protocol.registerStandardSchemes(['freetube']); app.setAsDefaultProtocolClient('freetube'); const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => { - // Someone tried to run a second instance, we should focus our window. - if (win) { - if (win.isMinimized()) win.restore() - win.focus() + // Someone tried to run a second instance, we should focus our window. + if (win) { + if (win.isMinimized()) win.restore() + win.focus() - win.webContents.send('ping', commandLine) - } + win.webContents.send('ping', commandLine) + } }); -if(require('electron-squirrel-startup') || isSecondInstance) app.quit(); +if (require('electron-squirrel-startup') || isSecondInstance) app.quit(); /** * Initialize the Electron application * 1. create the browser window * 2. load the index.html */ -let init = function() { - const Menu = require('electron').Menu; +let init = function () { + const Menu = require('electron').Menu; - win = new BrowserWindow({width: 1200, height: 800, autoHideMenuBar: true}); + win = new BrowserWindow({ + width: 1200, + height: 800, + autoHideMenuBar: true + }); - win.loadURL(url.format({ - pathname: path.join(__dirname, '../index.html'), - protocol: 'file:', - slashes: true, - })); + win.loadURL(url.format({ + pathname: path.join(__dirname, '../index.html'), + protocol: 'file:', + slashes: true, + })); - if (process.env = 'development') { - //win.webContents.openDevTools();ff - } - - win.on('closed', () => { - win = null; - }); - - const template = [ - { - label: 'File', - submenu: [ - {role: 'quit'} - ] - }, - { - label: 'Edit', - submenu: [ - {role: 'cut'}, - {role: 'copy', accelerator: "CmdOrCtrl+C", selector: "copy:" }, - {role: 'paste', accelerator: "CmdOrCtrl+V", selector: "paste:" }, - {role: 'pasteandmatchstyle'}, - {role: 'delete'}, - {role: 'selectall'} - ] - }, - { - label: 'View', - submenu: [ - {role: 'reload'}, - {role: 'forcereload'}, - {role: 'toggledevtools'}, - {type: 'separator'}, - {role: 'resetzoom'}, - {role: 'zoomin'}, - {role: 'zoomout'}, - {type: 'separator'}, - {role: 'togglefullscreen'} - ] - }, - { - role: 'window', - submenu: [ - {role: 'minimize'}, - {role: 'close'} - ] + if (process.env = 'development') { + //win.webContents.openDevTools();ff } - ]; - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); + win.on('closed', () => { + win = null; + }); + + const template = [{ + label: 'File', + submenu: [{ + role: 'quit' + }] + }, + { + label: 'Edit', + submenu: [{ + role: 'cut' + }, + { + role: 'copy', + accelerator: "CmdOrCtrl+C", + selector: "copy:" + }, + { + role: 'paste', + accelerator: "CmdOrCtrl+V", + selector: "paste:" + }, + { + role: 'pasteandmatchstyle' + }, + { + role: 'delete' + }, + { + role: 'selectall' + } + ] + }, + { + label: 'View', + submenu: [{ + role: 'reload' + }, + { + role: 'forcereload' + }, + { + role: 'toggledevtools' + }, + { + type: 'separator' + }, + { + role: 'resetzoom' + }, + { + role: 'zoomin' + }, + { + role: 'zoomout' + }, + { + type: 'separator' + }, + { + role: 'togglefullscreen' + } + ] + }, + { + role: 'window', + submenu: [{ + role: 'minimize' + }, + { + role: 'close' + } + ] + } + ]; + + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); }; /** * Quit the application */ -let allWindowsClosed = function() { - win.webContents.session.clearStorageData([], (data) => {}); - win.webContents.session.clearCache((data) => {}); - app.quit(); +let allWindowsClosed = function () { + win.webContents.session.clearStorageData([], (data) => {}); + win.webContents.session.clearCache((data) => {}); + app.quit(); }; /** * On Mac, when dock icon is clicked, * create a new window and launch the editor */ -let active = function() { - if (win === null) { - init(); - } +let active = function () { + if (win === null) { + init(); + } }; /** @@ -136,4 +180,4 @@ let active = function() { */ app.on('ready', init); app.on('window-all-closed', allWindowsClosed); -app.on('activate', active); +app.on('activate', active); \ No newline at end of file diff --git a/src/js/layout.js b/src/js/layout.js index 75734d019..9d27968e4 100644 --- a/src/js/layout.js +++ b/src/js/layout.js @@ -1,18 +1,18 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If nsot, see . */ @@ -54,73 +54,73 @@ let dialog = electron.remote.dialog; // Used for opening file browser to export let toastTimeout; // Timeout for toast notifications. let mouseTimeout; // Timeout for hiding the mouse cursor on video playback -require.extensions['.html'] = function(module, filename) { - module.exports = fs.readFileSync(filename, 'utf8'); +require.extensions['.html'] = function (module, filename) { + module.exports = fs.readFileSync(filename, 'utf8'); }; const subDb = new Datastore({ - filename: localDataStorage + '/subscriptions.db', - autoload: true + filename: localDataStorage + '/subscriptions.db', + autoload: true }); const historyDb = new Datastore({ - filename: localDataStorage + '/videohistory.db', - autoload: true + filename: localDataStorage + '/videohistory.db', + autoload: true }); const savedVidsDb = new Datastore({ - filename: localDataStorage + '/savedvideos.db', - autoload: true + filename: localDataStorage + '/savedvideos.db', + autoload: true }); const settingsDb = new Datastore({ - filename: localDataStorage + '/settings.db', - autoload: true + filename: localDataStorage + '/settings.db', + autoload: true }); // Grabs the default settings from the settings database file. Makes defaults if // none are found. checkDefaultSettings(); -require('electron').ipcRenderer.on('ping', function(event, message) { - console.log(message); +require('electron').ipcRenderer.on('ping', function (event, message) { + ft.log(message); let url = message[1].replace('freetube://', ''); parseSearchText(url); - console.log(message); + ft.log(message); }); // Open links externally by default $(document).on('click', 'a[href^="http"]', (event) => { - let el = event.currentTarget; - event.preventDefault(); - shell.openExternal(el.href); + let el = event.currentTarget; + event.preventDefault(); + shell.openExternal(el.href); }); // Open links externally on middle click. $(document).on('auxclick', 'a[href^="http"]', (event) => { - let el = event.currentTarget; - event.preventDefault(); - shell.openExternal(el.href); + let el = event.currentTarget; + event.preventDefault(); + shell.openExternal(el.href); }); $(document).ready(() => { - const searchBar = document.getElementById('search'); - const jumpToInput = document.getElementById('jumpToInput'); + const searchBar = document.getElementById('search'); + const jumpToInput = document.getElementById('jumpToInput'); - // Displays the list of subscriptions in the side bar. - displaySubs(); + // Displays the list of subscriptions in the side bar. + displaySubs(); - // Allow user to use the 'enter' key to search for a video. - searchBar.onkeypress = (e) => { - if (e.keyCode === 13) { - parseSearchText(); - } - }; + // Allow user to use the 'enter' key to search for a video. + searchBar.onkeypress = (e) => { + if (e.keyCode === 13) { + parseSearchText(); + } + }; - // Display subscriptions upon the app opening up. May allow user to specify. - // Home page in the future. - loadSubscriptions(); + // Display subscriptions upon the app opening up. May allow user to specify. + // Home page in the future. + loadSubscriptions(); }); /** @@ -129,16 +129,16 @@ $(document).ready(() => { * @return {Void} */ function toggleSideNavigation() { - const sideNav = document.getElementById('sideNav'); - const mainContainer = document.getElementById('main'); + const sideNav = document.getElementById('sideNav'); + const mainContainer = document.getElementById('main'); - if (sideNav.style.display === 'none') { - sideNav.style.display = 'inline'; - mainContainer.style.marginLeft = '250px'; - } else { - sideNav.style.display = 'none'; - mainContainer.style.marginLeft = '0px'; - } + if (sideNav.style.display === 'none') { + sideNav.style.display = 'inline'; + mainContainer.style.marginLeft = '250px'; + } else { + sideNav.style.display = 'none'; + mainContainer.style.marginLeft = '0px'; + } } /** @@ -147,35 +147,35 @@ function toggleSideNavigation() { * @return {Void} */ function clearMainContainer() { - const container = document.getElementById('main'); - container.innerHTML = ''; - hideConfirmFunction(); + const container = document.getElementById('main'); + container.innerHTML = ''; + hideConfirmFunction(); } function startLoadingAnimation() { - const loading = document.getElementById('loading'); - const sideNavDisabled = document.getElementById('sideNavDisabled'); - const searchBar = document.getElementById('search'); + const loading = document.getElementById('loading'); + const sideNavDisabled = document.getElementById('sideNavDisabled'); + const searchBar = document.getElementById('search'); - loading.style.display = 'inherit'; - if(sideNavDisabled !== null){ - sideNavDisabled.style.display = 'inherit'; - } + loading.style.display = 'inherit'; + if (sideNavDisabled !== null) { + sideNavDisabled.style.display = 'inherit'; + } - searchBar.disabled = true; + searchBar.disabled = true; } function stopLoadingAnimation() { - const loading = document.getElementById('loading'); - const sideNavDisabled = document.getElementById('sideNavDisabled'); - const searchBar = document.getElementById('search'); + const loading = document.getElementById('loading'); + const sideNavDisabled = document.getElementById('sideNavDisabled'); + const searchBar = document.getElementById('search'); - loading.style.display = 'none'; - if(sideNavDisabled !== null){ - sideNavDisabled.style.display = 'none'; - } + loading.style.display = 'none'; + if (sideNavDisabled !== null) { + sideNavDisabled.style.display = 'none'; + } - searchBar.disabled = false; + searchBar.disabled = false; } /** @@ -186,17 +186,17 @@ function stopLoadingAnimation() { * @return {Void} */ function createVideoListContainer(headerLabel = '') { - const videoListContainer = document.createElement("div"); - videoListContainer.id = 'videoListContainer'; - let headerSpacer; - if (headerLabel != '') { - const headerElement = document.createElement("h2"); - headerElement.innerHTML = headerLabel; - headerElement.style.marginLeft = '15px'; - headerElement.appendChild(document.createElement("hr")); - videoListContainer.appendChild(headerElement); - } - document.getElementById("main").appendChild(videoListContainer); + const videoListContainer = document.createElement("div"); + videoListContainer.id = 'videoListContainer'; + let headerSpacer; + if (headerLabel != '') { + const headerElement = document.createElement("h2"); + headerElement.innerHTML = headerLabel; + headerElement.style.marginLeft = '15px'; + headerElement.appendChild(document.createElement("hr")); + videoListContainer.appendChild(headerElement); + } + document.getElementById("main").appendChild(videoListContainer); } /** @@ -205,18 +205,18 @@ function createVideoListContainer(headerLabel = '') { * @return {Void} */ function showAbout() { - // Remove current information and display loading animation - clearMainContainer(); - startLoadingAnimation(); + // Remove current information and display loading animation + clearMainContainer(); + startLoadingAnimation(); - const aboutTemplate = require('./templates/about.html') - mustache.parse(aboutTemplate); - $('#main').html( - mustache.render(aboutTemplate, { - versionNumber: require('electron').remote.app.getVersion(), - }) - ); - stopLoadingAnimation(); + const aboutTemplate = require('./templates/about.html') + mustache.parse(aboutTemplate); + $('#main').html( + mustache.render(aboutTemplate, { + versionNumber: require('electron').remote.app.getVersion(), + }) + ); + stopLoadingAnimation(); } /** @@ -228,18 +228,18 @@ function showAbout() { * @return {Void} */ function showToast(message) { - let toast = document.getElementById('toast'); - let toastMessage = document.getElementById('toastMessage'); + let toast = document.getElementById('toast'); + let toastMessage = document.getElementById('toastMessage'); - // If a toast message is already being displayed, this will remove the previous timer that was set. - clearTimeout(toastTimeout); + // If a toast message is already being displayed, this will remove the previous timer that was set. + clearTimeout(toastTimeout); - toastMessage.innerHTML = message; - toast.style.visibility = 'visible'; - toast.style.opacity = 0.9; + toastMessage.innerHTML = message; + toast.style.visibility = 'visible'; + toast.style.opacity = 0.9; - // Set the timer for the toast to be removed. - toastTimeout = window.setTimeout(hideToast, 5000); + // Set the timer for the toast to be removed. + toastTimeout = window.setTimeout(hideToast, 5000); } /** @@ -248,9 +248,9 @@ function showToast(message) { * @return {Void} */ function hideToast() { - let toast = document.getElementById('toast'); - toast.style.opacity = 0; - toast.style.visibility = 'hidden'; + let toast = document.getElementById('toast'); + toast.style.opacity = 0; + toast.style.visibility = 'hidden'; } /** @@ -264,21 +264,20 @@ function hideToast() { * @return {Void} */ function confirmFunction(message, performFunction, parameters = '') { - let confirmContainer = document.getElementById('confirmFunction'); - let confirmMessage = document.getElementById('confirmMessage'); + let confirmContainer = document.getElementById('confirmFunction'); + let confirmMessage = document.getElementById('confirmMessage'); - confirmMessage.innerHTML = message; - confirmContainer.style.visibility = 'visible'; + confirmMessage.innerHTML = message; + confirmContainer.style.visibility = 'visible'; - $(document).on('click', '#confirmYes', (event) => { - if(parameters != ''){ - performFunction(parameters); - } - else{ - performFunction(); - } - hideConfirmFunction(); - }); + $(document).on('click', '#confirmYes', (event) => { + if (parameters != '') { + performFunction(parameters); + } else { + performFunction(); + } + hideConfirmFunction(); + }); } /** @@ -287,8 +286,8 @@ function confirmFunction(message, performFunction, parameters = '') { * @return {Void} */ function hideConfirmFunction() { - let confirmContainer = document.getElementById('confirmFunction'); - confirmContainer.style.visibility = 'hidden'; + let confirmContainer = document.getElementById('confirmFunction'); + confirmContainer.style.visibility = 'hidden'; } /** @@ -298,11 +297,11 @@ function hideConfirmFunction() { * @return {Void} */ function hideMouseTimeout() { - $('.videoPlayer')[0].style.cursor = 'default'; - clearTimeout(mouseTimeout); - mouseTimeout = window.setTimeout(function() { - $('.videoPlayer')[0].style.cursor = 'none'; - }, 3150); + $('.videoPlayer')[0].style.cursor = 'default'; + clearTimeout(mouseTimeout); + mouseTimeout = window.setTimeout(function () { + $('.videoPlayer')[0].style.cursor = 'none'; + }, 3150); } /** @@ -311,14 +310,14 @@ function hideMouseTimeout() { * @return {Void} */ function removeMouseTimeout() { - $('.videoPlayer')[0].style.cursor = 'default'; - clearTimeout(mouseTimeout); + $('.videoPlayer')[0].style.cursor = 'default'; + clearTimeout(mouseTimeout); } function showVideoOptions(element) { - if (element.nextElementSibling.style.display == 'none' || element.nextElementSibling.style.display == '') { - element.nextElementSibling.style.display = 'inline-block' - } else { - element.nextElementSibling.style.display = 'none' - } -} + if (element.nextElementSibling.style.display == 'none' || element.nextElementSibling.style.display == '') { + element.nextElementSibling.style.display = 'inline-block' + } else { + element.nextElementSibling.style.display = 'none' + } +} \ No newline at end of file diff --git a/src/js/models/comment.model.js b/src/js/models/comment.model.js index 854f85b31..79ffd5570 100644 --- a/src/js/models/comment.model.js +++ b/src/js/models/comment.model.js @@ -1,18 +1,18 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ @@ -21,9 +21,9 @@ along with FreeTube. If not, see . * Video Comment Model */ export class comment { - authorDisplayName: string; - authorProfileImageUrl: string; - authorChannelId: string; - textDisplay: string; - publishedAt: string; -} + authorDisplayName; + authorProfileImageUrl; + authorChannelId; + textDisplay; + publishedAt; +} \ No newline at end of file diff --git a/src/js/models/commentThread.model.js b/src/js/models/commentThread.model.js index e54de7878..fef1105f9 100644 --- a/src/js/models/commentThread.model.js +++ b/src/js/models/commentThread.model.js @@ -1,33 +1,35 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ -import {comment} from "./comment.model"; +import { + comment +} from "./comment.model"; /** * Entire Comment Threads for a Video */ export class commentThread { - videoId: ?string; - nextPageToken: ?string; - pageInfo: { - totalResults: number, - resultsPerPage: number + videoId; + nextPageToken; + pageInfo = { + totalResults, + resultsPerPage }; - items: comment[]; -} + items; +} \ No newline at end of file diff --git a/src/js/player.js b/src/js/player.js index fccc516d4..89a1725d1 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1,18 +1,18 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ @@ -29,240 +29,234 @@ along with FreeTube. If not, see . * @return {Void} */ function playVideo(videoId, videoThumbnail = '', useWindowPlayer = false) { - if (useWindowPlayer === false){ - clearMainContainer(); - startLoadingAnimation(); - } - else{ - showToast('Getting video information. Please wait...') - } - - let subscribeText = ''; - let savedText = ''; - let savedIconClass = ''; - let savedIconColor = ''; - let video480p; - let video720p; - let videoSubtitles = ''; - let subtitleHtml = ''; - let subtitleLabel; - let subtitleLanguage; - let subtitleCode; - let subtitleUrl; - let defaultUrl; - let defaultQuality; - let channelId; - let videoHtml; - let videoType = 'video'; - let embedPlayer = ""; - let useEmbedPlayer = false; - let validUrl; - let videoLikes; - let videoDislikes; - let totalLikes; - let likePercentage; - - const checkSavedVideo = videoIsSaved(videoId); - - // Change the save button icon and text depending on if the user has saved the video or not. - checkSavedVideo.then((results) => { - if (results === false) { - savedText = 'SAVE'; - savedIconClass = 'far unsaved'; + if (useWindowPlayer === false) { + clearMainContainer(); + startLoadingAnimation(); } else { - savedText = 'SAVED'; - savedIconClass = 'fas saved'; + showToast('Getting video information. Please wait...') } - }); - youtubeAPI('videos', { - part: 'statistics', - id: videoId, - }, function(data) { - console.log(data); + let subscribeText = ''; + let savedText = ''; + let savedIconClass = ''; + let savedIconColor = ''; + let video480p; + let video720p; + let videoSubtitles = ''; + let subtitleHtml = ''; + let subtitleLabel; + let subtitleLanguage; + let subtitleCode; + let subtitleUrl; + let defaultUrl; + let defaultQuality; + let channelId; + let videoHtml; + let videoType = 'video'; + let embedPlayer = ""; + let useEmbedPlayer = false; + let validUrl; + let videoLikes; + let videoDislikes; + let totalLikes; + let likePercentage; - // Figure out the width for the like/dislike bar. - videoLikes = data['items'][0]['statistics']['likeCount']; - videoDislikes = data['items'][0]['statistics']['dislikeCount']; - totalLikes = parseInt(videoLikes) + parseInt(videoDislikes); - likePercentage = parseInt((videoLikes / totalLikes) * 100); - }); + const checkSavedVideo = videoIsSaved(videoId); - /* - * FreeTube calls youtube-dl to grab the direct video URL. - */ - youtubedlGetInfo(videoId, (info) => { - console.log(info); - - console.log(videoLikes); - - channelId = info['author']['id']; - let channelThumbnail = info['author']['avatar']; - - let videoUrls = info['formats']; - - // Add commas to the video view count. - const videoViews = info['view_count'].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); - - videoThumbnail = info['player_response']['videoDetails']['thumbnail']['thumbnails'][3]['url']; - - // Format the date to a more readable format. - let dateString = new Date(info['published']); - dateString.setDate(dateString.getDate() + 1); - const publishedDate = dateFormat(dateString, "mmm dS, yyyy"); - - let description = info['description']; - // Adds clickable links to the description. - description = autolinker.link(description); - - // Search through the returned object to get the 480p and 720p video URLs (If available) - Object.keys(videoUrls).forEach((key) => { - switch (videoUrls[key]['itag']) { - case '18': - video480p = decodeURIComponent(videoUrls[key]['url']); - console.log(video480p); - break; - case '22': - video720p = decodeURIComponent(videoUrls[key]['url']); - console.log(video720p); - break; - } + // Change the save button icon and text depending on if the user has saved the video or not. + checkSavedVideo.then((results) => { + if (results === false) { + savedText = 'FAVORITE'; + savedIconClass = 'far unsaved'; + } else { + savedText = 'UNFAVORITE'; + savedIconClass = 'fas saved'; + } }); - // Default to the embeded player if the URLs cannot be found. - if (typeof(video720p) === 'undefined' && typeof(video480p) === 'undefined') { - useEmbedPlayer = true; - defaultQuality = 'EMBED'; - videoHtml = embedPlayer.replace(/\"\;/g, '"'); - showToast('Unable to get video file. Reverting to embeded player.'); - } else if (typeof(video720p) === 'undefined' && typeof(video480p) !== 'undefined') { - // Default to the 480p video if the 720p URL cannot be found. - defaultUrl = video480p; - defaultQuality = '480p'; - } else { - // Default to the 720p video. - defaultUrl = video720p; - defaultQuality = '720p'; - // Force the embeded player if needed. - //videoHtml = embedPlayer; - } + youtubeAPI('videos', { + part: 'statistics', + id: videoId, + }, function (data) { - if (!useEmbedPlayer) { - //videoHtml = ''; - } + const checkSubscription = isSubscribed(channelId); - const checkSubscription = isSubscribed(channelId); + // Change the subscribe button text depending on if the user has subscribed to the channel or not. - // Change the subscribe button text depending on if the user has subscribed to the channel or not. + checkSubscription.then((results) => { + const subscribeButton = document.getElementById('subscribeButton'); - checkSubscription.then((results) => { - const subscribeButton = document.getElementById('subscribeButton'); - - if (results === false) { - if (subscribeButton != null) { - subscribeButton.innerHTML = 'SUBSCRIBE'; - } - } else { - if (subscribeButton != null) { - subscribeButton.innerHTML = 'UNSUBSCRIBE'; - } - } - }); - - const playerTemplate = require('./templates/player.html') - mustache.parse(playerTemplate); - const rendered = mustache.render(playerTemplate, { - videoQuality: defaultQuality, - subtitleHtml: videoHtml, - defaultUrl: defaultUrl, - videoTitle: info['title'], - videoViews: videoViews, - videoThumbnail: videoThumbnail, - channelName: info['author']['name'], - videoLikes: videoLikes, - videoDislikes: videoDislikes, - likePercentage: likePercentage, - videoId: videoId, - channelId: channelId, - channelIcon: channelThumbnail, - publishedDate: publishedDate, - description: description, - isSubscribed: subscribeText, - savedText: savedText, - savedIconClass: savedIconClass, - savedIconColor: savedIconColor, - video480p: video480p, - video720p: video720p, - embedPlayer: embedPlayer, - }); - - // Add the video to the user's history - addToHistory(videoId); - - if (useWindowPlayer){ - // Create a new browser window. - const BrowserWindow = electron.remote.BrowserWindow; - - let newWindow = new BrowserWindow({ - width: 1200, - height: 700 - }); - - let playerWindowHeader = require('./templates/playerWindow.html'); - - mustache.parse(playerWindowHeader); - const playerHeaderRender = mustache.render(playerWindowHeader, { - videoId: videoId, - channelId: channelId - }); - - newWindow.loadURL('data:text/html;charset=UTF-8,' + encodeURIComponent(playerHeaderRender + rendered), { - baseURLForDataURL: `file://${__dirname}/src` - }); - } - else{ - $('#main').html(rendered); - stopLoadingAnimation(); - - showVideoRecommendations(videoId); - - // Hide subtitles by default - if (typeof(info['subtitles']) !== 'undefined' && Object.keys(info['subtitles']).length > 0) { - let textTracks = $('.videoPlayer').get(0).textTracks; - Object.keys(textTracks).forEach((track) => { - textTracks[track].mode = 'hidden'; + if (results === false) { + if (subscribeButton != null) { + subscribeButton.innerHTML = 'SUBSCRIBE'; + } + } else { + if (subscribeButton != null) { + subscribeButton.innerHTML = 'UNSUBSCRIBE'; + } + } }); - } - } - // Sometimes a video URL is found, but the video will not play. I believe the issue is - // that the video has yet to render for that quality, as the video will be available at a later time. - // This will check the URLs and switch video sources if there is an error. - //checkVideoUrls(video480p, video720p); + const playerTemplate = require('./templates/player.html') + mustache.parse(playerTemplate); + const rendered = mustache.render(playerTemplate, { + videoQuality: defaultQuality, + subtitleHtml: videoHtml, + defaultUrl: defaultUrl, + videoTitle: info['title'], + videoViews: videoViews, + videoThumbnail: videoThumbnail, + channelName: info['author']['name'], + videoLikes: videoLikes, + videoDislikes: videoDislikes, + likePercentage: likePercentage, + videoId: videoId, + channelId: channelId, + channelIcon: channelThumbnail, + publishedDate: publishedDate, + description: description, + isSubscribed: subscribeText, + savedText: savedText, + savedIconClass: savedIconClass, + savedIconColor: savedIconColor, + video480p: video480p, + video720p: video720p, + embedPlayer: embedPlayer, + }); - window.setTimeout(checkVideoUrls, 5000, video480p, video720p); + // Add the video to the user's history + addToHistory(videoId); - }); + if (useWindowPlayer) { + // Create a new browser window. + const BrowserWindow = electron.remote.BrowserWindow; + + let newWindow = new BrowserWindow({ + width: 1200, + height: 700 + }); + + let playerWindowHeader = require('./templates/playerWindow.html'); + + mustache.parse(playerWindowHeader); + const playerHeaderRender = mustache.render(playerWindowHeader, { + videoId: videoId, + channelId: channelId + }); + + newWindow.loadURL('data:text/html;charset=UTF-8,' + encodeURIComponent(playerHeaderRender + rendered), { + baseURLForDataURL: `file://${__dirname}/src` + }); + } else { + $('#main').html(rendered); + stopLoadingAnimation(); + + showVideoRecommendations(videoId); + + // Hide subtitles by default + if (typeof (info['subtitles']) !== 'undefined' && Object.keys(info['subtitles']).length > 0) { + let textTracks = $('.videoPlayer').get(0).textTracks; + Object.keys(textTracks).forEach((track) => { + textTracks[track].mode = 'hidden'; + }); + } + } + + // Sometimes a video URL is found, but the video will not play. I believe the issue is + // that the video has yet to render for that quality, as the video will be available at a later time. + // This will check the URLs and switch video sources if there is an error. + //checkVideoUrls(video480p, video720p); + + window.setTimeout(checkVideoUrls, 5000, video480p, video720p); + + }); } /** @@ -273,38 +267,38 @@ function playVideo(videoId, videoThumbnail = '', useWindowPlayer = false) { * @return {Void} */ function openMiniPlayer(videoThumbnail) { - let lastTime; - let videoHtml; + let lastTime; + let videoHtml; - // Grabs whatever the HTML is for the current video player. Done this way to grab - // the HTML5 player (with varying qualities) as well as the YouTube embeded player. - if ($('.videoPlayer').length > 0) { - $('.videoPlayer').get(0).pause(); - lastTime = $('.videoPlayer').get(0).currentTime; - videoHtml = $('.videoPlayer').get(0).outerHTML; - } else { - videoHtml = $('iframe').get(0).outerHTML; - } + // Grabs whatever the HTML is for the current video player. Done this way to grab + // the HTML5 player (with varying qualities) as well as the YouTube embeded player. + if ($('.videoPlayer').length > 0) { + $('.videoPlayer').get(0).pause(); + lastTime = $('.videoPlayer').get(0).currentTime; + videoHtml = $('.videoPlayer').get(0).outerHTML; + } else { + videoHtml = $('iframe').get(0).outerHTML; + } - // Create a new browser window. - const BrowserWindow = electron.remote.BrowserWindow; + // Create a new browser window. + const BrowserWindow = electron.remote.BrowserWindow; - let miniPlayer = new BrowserWindow({ - width: 1200, - height: 710 - }); - - // Use the miniPlayer.html template. - $.get('templates/miniPlayer.html', (template) => { - mustache.parse(template); - const rendered = mustache.render(template, { - videoHtml: videoHtml, - videoThumbnail: videoThumbnail, - startTime: lastTime, + let miniPlayer = new BrowserWindow({ + width: 1200, + height: 710 + }); + + // Use the miniPlayer.html template. + $.get('templates/miniPlayer.html', (template) => { + mustache.parse(template); + const rendered = mustache.render(template, { + videoHtml: videoHtml, + videoThumbnail: videoThumbnail, + startTime: lastTime, + }); + // Render the template to the new browser window. + miniPlayer.loadURL("data:text/html;charset=utf-8," + encodeURI(rendered)); }); - // Render the template to the new browser window. - miniPlayer.loadURL("data:text/html;charset=utf-8," + encodeURI(rendered)); - }); } /** @@ -317,53 +311,53 @@ function openMiniPlayer(videoThumbnail) { * @return {Void} */ function changeQuality(videoHtml, qualityType, isEmbed = false) { - if (videoHtml == '') { - showToast('Video quality type is not available. Unable to change quality.') - return; - } + if (videoHtml == '') { + showToast('Video quality type is not available. Unable to change quality.') + return; + } - videoHtml = videoHtml.replace(/\"\;/g, '"'); + videoHtml = videoHtml.replace(/\"\;/g, '"'); - console.log(videoHtml); - console.log(isEmbed); + ft.log('HTML Video: ', videoHtml); + ft.log('(Is the video embeded?) isEmbed: ', isEmbed); - // The YouTube API creates 2 more iFrames. This is why a boolean value is sent - // with the function. - const embedPlayer = document.getElementsByTagName('IFRAME')[0]; + // The YouTube API creates 2 more iFrames. This is why a boolean value is sent + // with the function. + const embedPlayer = document.getElementsByTagName('IFRAME')[0]; - const html5Player = document.getElementsByClassName('videoPlayer'); + const html5Player = document.getElementsByClassName('videoPlayer'); - console.log(embedPlayer); - console.log(html5Player); + ft.log('Embeded Player Element: ', embedPlayer); + ft.log('HTML5 Player Element: ', html5Player); - if (isEmbed && html5Player.length == 0) { - // The embeded player is already playing. Return. - showToast('You are already using the embeded player.') - return; - } else if (isEmbed) { - // Switch from HTML 5 player to embeded Player - html5Player[0].remove(); - const mainHtml = $('#main').html(); - $('#main').html(videoHtml + mainHtml); - $('#currentQuality').html(qualityType); - } else if (html5Player.length == 0) { - // Switch from embeded player to HTML 5 player - embedPlayer.remove(); - let videoPlayer = document.createElement('video'); - videoPlayer.className = 'videoPlayer'; - videoPlayer.src = videoHtml; - videoPlayer.controls = true; - videoPlayer.autoplay = true; - $('#main').prepend(videoPlayer); - $('#currentQuality').html(qualityType); - } else { - // Switch src on HTML 5 player - const currentPlayBackTime = $('.videoPlayer').get(0).currentTime; - html5Player[0].src = videoHtml; - html5Player[0].load(); - $('.videoPlayer').get(0).currentTime = currentPlayBackTime; - $('#currentQuality').html(qualityType); - } + if (isEmbed && html5Player.length == 0) { + // The embeded player is already playing. Return. + showToast('You are already using the embeded player.') + return; + } else if (isEmbed) { + // Switch from HTML 5 player to embeded Player + html5Player[0].remove(); + const mainHtml = $('#main').html(); + $('#main').html(videoHtml + mainHtml); + $('#currentQuality').html(qualityType); + } else if (html5Player.length == 0) { + // Switch from embeded player to HTML 5 player + embedPlayer.remove(); + let videoPlayer = document.createElement('video'); + videoPlayer.className = 'videoPlayer'; + videoPlayer.src = videoHtml; + videoPlayer.controls = true; + videoPlayer.autoplay = true; + $('#main').prepend(videoPlayer); + $('#currentQuality').html(qualityType); + } else { + // Switch src on HTML 5 player + const currentPlayBackTime = $('.videoPlayer').get(0).currentTime; + html5Player[0].src = videoHtml; + html5Player[0].load(); + $('.videoPlayer').get(0).currentTime = currentPlayBackTime; + $('#currentQuality').html(qualityType); + } } /** @@ -374,8 +368,8 @@ function changeQuality(videoHtml, qualityType, isEmbed = false) { * @return {Void} */ function changeVideoSpeed(speed) { - $('#currentSpeed').html(speed); - $('.videoPlayer').get(0).playbackRate = speed; + $('#currentSpeed').html(speed); + $('.videoPlayer').get(0).playbackRate = speed; } /** @@ -386,16 +380,16 @@ function changeVideoSpeed(speed) { * @return {Void} */ function changeVolume(amount) { - const videoPlayer = $('.videoPlayer').get(0); - let volume = videoPlayer.volume; - volume = volume + amount; - if (volume > 1) { - videoPlayer.volume = 1; - } else if (volume < 0) { - videoPlayer.volume = 0; - } else { - videoPlayer.volume = volume; - } + const videoPlayer = $('.videoPlayer').get(0); + let volume = videoPlayer.volume; + volume = volume + amount; + if (volume > 1) { + videoPlayer.volume = 1; + } else if (volume < 0) { + videoPlayer.volume = 0; + } else { + videoPlayer.volume = volume; + } } /** @@ -406,8 +400,8 @@ function changeVolume(amount) { * @return {Void} */ function changeDurationBySeconds(seconds) { - const videoPlayer = $('.videoPlayer').get(0); - videoPlayer.currentTime = videoPlayer.currentTime + seconds; + const videoPlayer = $('.videoPlayer').get(0); + videoPlayer.currentTime = videoPlayer.currentTime + seconds; } /** @@ -418,6 +412,6 @@ function changeDurationBySeconds(seconds) { * @return {Void} */ function changeDurationByPercentage(percentage) { - const videoPlayer = $('.videoPlayer').get(0); - videoPlayer.currentTime = videoPlayer.duration * percentage; -} + const videoPlayer = $('.videoPlayer').get(0); + videoPlayer.currentTime = videoPlayer.duration * percentage; +} \ No newline at end of file diff --git a/src/js/savedVideos.js b/src/js/savedVideos.js index 39037d99f..83c8aa7b9 100644 --- a/src/js/savedVideos.js +++ b/src/js/savedVideos.js @@ -1,164 +1,164 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ /* -* File used for functions related to saving videos -*/ + * File used for functions related to saving videos + */ /** -* Adds a video to the user's saved video database. -* -* @param {string} videoId - The video ID of the video that will be saved. -* -* @return {Void} -*/ -function addSavedVideo(videoId){ - let checkIfSaved = videoIsSaved(videoId); + * Adds a video to the user's saved video database. + * + * @param {string} videoId - The video ID of the video that will be saved. + * + * @return {Void} + */ +function addSavedVideo(videoId) { + let checkIfSaved = videoIsSaved(videoId); - checkIfSaved.then((saved) => { - if (saved === false){ - let data = { - videoId: videoId, - timeSaved: new Date().getTime(), - }; + checkIfSaved.then((saved) => { + if (saved === false) { + let data = { + videoId: videoId, + timeSaved: new Date().getTime(), + }; - savedVidsDb.insert(data, (err, newDoc) => { - showToast('Video has been saved!'); - }); - } - else{ - showToast('Video already exists in saved file.') - } - }); + savedVidsDb.insert(data, (err, newDoc) => { + showToast('The video has been favorited!'); + }); + } else { + showToast('The video has already been favorited!') + } + }); } /** -* Removes a video from the user's saved video database. -* -* @param {string} videoId - The video ID of the video that will be removed. -* -* @return {Void} -*/ -function removeSavedVideo(videoId, string){ - savedVidsDb.remove({ - videoId: videoId - }, {}, (err, numRemoved) => { - showToast('Video has been removed from saved list.'); - }); + * Removes a video from the user's saved video database. + * + * @param {string} videoId - The video ID of the video that will be removed. + * + * @return {Void} + */ +function removeSavedVideo(videoId, string) { + savedVidsDb.remove({ + videoId: videoId + }, {}, (err, numRemoved) => { + showToast('Video has been removed from the favorites list.'); + }); } /** -* Toggles the save video button styling and saved / remove a video based on the current status. -* -* @param {string} videoId - The video ID to toggle between. -* -* @return {Void} -*/ + * Toggles the save video button styling and saved / remove a video based on the current status. + * + * @param {string} videoId - The video ID to toggle between. + * + * @return {Void} + */ function toggleSavedVideo(videoId) { - event.stopPropagation(); + event.stopPropagation(); - const checkIfSaved = videoIsSaved(videoId); - const saveIcon = document.getElementById('saveIcon'); - const savedText = document.getElementById('savedText'); + const checkIfSaved = videoIsSaved(videoId); + const saveIcon = document.getElementById('saveIcon'); + const savedText = document.getElementById('savedText'); - checkIfSaved.then((results) => { - if (results === false) { - savedText.innerHTML = 'SAVED'; - saveIcon.classList.remove('far'); - saveIcon.classList.remove('unsaved'); - saveIcon.classList.add('fas'); - saveIcon.classList.add('saved'); - addSavedVideo(videoId); - } else { - savedText.innerHTML = 'SAVE'; - saveIcon.classList.remove('fas'); - saveIcon.classList.remove('saved'); - saveIcon.classList.add('far'); - saveIcon.classList.add('unsaved'); - removeSavedVideo(videoId); - } - }); + checkIfSaved.then((results) => { + if (results === false) { + savedText.innerHTML = 'UNFAVORITE'; + saveIcon.classList.remove('far'); + saveIcon.classList.remove('unsaved'); + saveIcon.classList.add('fas'); + saveIcon.classList.add('saved'); + addSavedVideo(videoId); + } else { + savedText.innerHTML = 'FAVORITE'; + saveIcon.classList.remove('fas'); + saveIcon.classList.remove('saved'); + saveIcon.classList.add('far'); + saveIcon.classList.add('unsaved'); + removeSavedVideo(videoId); + } + }); } /** -* Checks if a video was saved in the user's saved video database -* -* @param {string} videoId - The video ID to check -* -* @return {promise} - A boolean value if the video was found or not. -*/ + * Checks if a video was saved in the user's saved video database + * + * @param {string} videoId - The video ID to check + * + * @return {promise} - A boolean value if the video was found or not. + */ function videoIsSaved(videoId) { - return new Promise((resolve, reject) => { - savedVidsDb.find({videoId: videoId}, (err, docs) => { - if (jQuery.isEmptyObject(docs)) { - resolve(false); - } else { - resolve(true); - } + return new Promise((resolve, reject) => { + savedVidsDb.find({ + videoId: videoId + }, (err, docs) => { + if (jQuery.isEmptyObject(docs)) { + resolve(false); + } else { + resolve(true); + } + }); }); - }); } /** -* Displays a list of the user's saved videos. -* -* @return {Void} -*/ -function showSavedVideos(){ - clearMainContainer(); - startLoadingAnimation(); - console.log('checking saved videos'); + * Displays a list of the user's saved videos. + * + * @return {Void} + */ +function showSavedVideos() { + clearMainContainer(); + startLoadingAnimation(); + ft.log('Checking favorited videos'); - let videoList = ''; + let videoList = ''; - // Check the database for the list of videos. - savedVidsDb.find({}).sort({ - timeSaved: -1 - }).exec((err, docs) => { - // The YouTube API requires a max of 50 videos to be shown. Don't show more than 50. - // TODO: Allow the app to show more than 50 saved videos. - if(docs.length > 49){ - for (let i = 0; i < 49; i++) { - videoList = videoList + ',' + docs[i].videoId; - } - } - else{ - docs.forEach((video) => { - videoList = videoList + ',' + video.videoId; - }); - } + // Check the database for the list of videos. + savedVidsDb.find({}).sort({ + timeSaved: -1 + }).exec((err, docs) => { + // The YouTube API requires a max of 50 videos to be shown. Don't show more than 50. + // TODO: Allow the app to show more than 50 saved videos. + if (docs.length > 49) { + for (let i = 0; i < 49; i++) { + videoList = videoList + ',' + docs[i].videoId; + } + } else { + docs.forEach((video) => { + videoList = videoList + ',' + video.videoId; + }); + } - // Call the YouTube API - youtubeAPI('videos', { - part: 'snippet', - id: videoList, - maxResults: 50, - }, (data) => { - // Render the videos to the screen - createVideoListContainer('Saved Videos:'); - let grabDuration = getDuration(data.items); - grabDuration.then((videoList) => { - videoList.items.forEach((video) => { - displayVideo(video, 'saved'); + // Call the YouTube API + youtubeAPI('videos', { + part: 'snippet', + id: videoList, + maxResults: 50, + }, (data) => { + // Render the videos to the screen + createVideoListContainer('Favorited Videos:'); + let grabDuration = getDuration(data.items); + grabDuration.then((videoList) => { + videoList.items.forEach((video) => { + displayVideo(video, 'saved'); + }); + }); + stopLoadingAnimation(); }); - }); - stopLoadingAnimation(); }); - }); -} +} \ No newline at end of file diff --git a/src/js/settings.js b/src/js/settings.js index 4aff3062d..add9de7b3 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -1,18 +1,18 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ @@ -30,55 +30,55 @@ const apiKeyBank = ['AIzaSyC9E579nh_qqxg6BH4xIce3k_7a9mT4uQc', 'AIzaSyCKplYT6hZI * @return {Void} */ function showSettings() { - clearMainContainer(); - startLoadingAnimation(); + clearMainContainer(); + startLoadingAnimation(); - let isChecked = ''; - let key = ''; + let isChecked = ''; + let key = ''; - /* - * Check the settings database for the user's current settings. This is so the - * settings page has the correct toggles related when it is rendered. - */ - settingsDb.find({}, (err, docs) => { - docs.forEach((setting) => { - switch (setting['_id']) { - case 'apiKey': - if (apiKeyBank.indexOf(setting['value']) == -1) { - key = setting['value']; - } - break; - case 'theme': - if (currentTheme == '') { - currentTheme = setting['value']; - } - } + /* + * Check the settings database for the user's current settings. This is so the + * settings page has the correct toggles related when it is rendered. + */ + settingsDb.find({}, (err, docs) => { + docs.forEach((setting) => { + switch (setting['_id']) { + case 'apiKey': + if (apiKeyBank.indexOf(setting['value']) == -1) { + key = setting['value']; + } + break; + case 'theme': + if (currentTheme == '') { + currentTheme = setting['value']; + } + } + }); + + // Grab the settings.html template to prepare for rendering + const settingsTemplate = require('./templates/settings.html') + mustache.parse(settingsTemplate); + const rendered = mustache.render(settingsTemplate, { + isChecked: isChecked, + key: key, + }); + // Render template to application + $('#main').html(rendered); + stopLoadingAnimation(); + + // Check / uncheck the switch depending on the user's settings. + if (currentTheme === 'light') { + document.getElementById('themeSwitch').checked = false; + } else { + document.getElementById('themeSwitch').checked = true; + } + + if (useTor) { + document.getElementById('torSwitch').checked = true; + } else { + document.getElementById('torSwitch').checked = false; + } }); - - // Grab the settings.html template to prepare for rendering - const settingsTemplate = require('./templates/settings.html') - mustache.parse(settingsTemplate); - const rendered = mustache.render(settingsTemplate, { - isChecked: isChecked, - key: key, - }); - // Render template to application - $('#main').html(rendered); - stopLoadingAnimation(); - - // Check / uncheck the switch depending on the user's settings. - if (currentTheme === 'light') { - document.getElementById('themeSwitch').checked = false; - } else { - document.getElementById('themeSwitch').checked = true; - } - - if (useTor) { - document.getElementById('torSwitch').checked = true; - } else { - document.getElementById('torSwitch').checked = false; - } - }); } /** @@ -88,51 +88,52 @@ function showSettings() { */ function checkDefaultSettings() { - // Grab a random API Key. - apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; - let newSetting; + // Grab a random API Key. + apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; + let newSetting; - let settingDefaults = { - 'theme': 'light', - 'apiKey': apiKey, - 'useTor': false - }; + let settingDefaults = { + 'theme': 'light', + 'apiKey': apiKey, + 'useTor': false + }; - console.log(settingDefaults); + ft.log('Default Settings: ', settingDefaults); - for (let key in settingDefaults){ - settingsDb.find({_id: key}, (err, docs) => { - if (jQuery.isEmptyObject(docs)) { - newSetting = { - _id: key, - value: settingDefaults[key] - }; + for (let key in settingDefaults) { + settingsDb.find({ + _id: key + }, (err, docs) => { + if (jQuery.isEmptyObject(docs)) { + newSetting = { + _id: key, + value: settingDefaults[key] + }; - settingsDb.insert(newSetting); + settingsDb.insert(newSetting); - if (key == 'theme'){ - setTheme('light'); - } - } - else{ - switch (docs[0]['_id']) { - case 'theme': - setTheme(docs[0]['value']); - break; - case 'apiKey': - if (apiKeyBank.indexOf(docs[0]['value']) == -1) { - apiKey = docs[0]['value']; + if (key == 'theme') { + setTheme('light'); + } + } else { + switch (docs[0]['_id']) { + case 'theme': + setTheme(docs[0]['value']); + break; + case 'apiKey': + if (apiKeyBank.indexOf(docs[0]['value']) == -1) { + apiKey = docs[0]['value']; + } + break; + case 'useTor': + useTor = docs[0]['value']; + break; + default: + break; + } } - break; - case 'useTor': - useTor = docs[0]['value']; - break; - default: - break; - } - } - }); - } + }); + } } /** @@ -141,58 +142,58 @@ function checkDefaultSettings() { * @return {Void} */ function updateSettings() { - let themeSwitch = document.getElementById('themeSwitch').checked; - let torSwitch = document.getElementById('torSwitch').checked; - let key = document.getElementById('api-key').value; - let theme = 'light'; + let themeSwitch = document.getElementById('themeSwitch').checked; + let torSwitch = document.getElementById('torSwitch').checked; + let key = document.getElementById('api-key').value; + let theme = 'light'; - apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; + apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)]; - console.log(themeSwitch); + ft.log('(Is the theme switch checked) themeSwitch: ', themeSwitch); - if (themeSwitch === true) { - theme = 'dark'; - } + if (themeSwitch === true) { + theme = 'dark'; + } - console.log(theme); + ft.log('Theme: ', theme); - // Update default theme - settingsDb.update({ - _id: 'theme' - }, { - value: theme - }, {}, function(err, numReplaced) { - console.log(err); - console.log(numReplaced); - }); - - // Update tor usage. - settingsDb.update({ - _id: 'useTor' - }, { - value: torSwitch - }, {}, function(err, numReplaced) { - console.log(err); - console.log(numReplaced); - useTor = torSwitch; - }); - - if (key != '') { + // Update default theme settingsDb.update({ - _id: 'apiKey' + _id: 'theme' }, { - value: key - }, {}); - } else { - // To any third party devs that fork the project, please be ethical and change the API key. - settingsDb.update({ - _id: 'apiKey' - }, { - value: apiKey - }, {}); - } + value: theme + }, {}, function (err, numReplaced) { + ft.log('Error while updating theme: ', err); + ft.log('Number replaced: ', numReplaced); + }); - showToast('Settings have been saved.'); + // Update tor usage. + settingsDb.update({ + _id: 'useTor' + }, { + value: torSwitch + }, {}, function (err, numReplaced) { + ft.log('Error while connecting to tor: ', err); + ft.log('Number replaced: ', numReplaced); + useTor = torSwitch; + }); + + if (key != '') { + settingsDb.update({ + _id: 'apiKey' + }, { + value: key + }, {}); + } else { + // To any third party devs that fork the project, please be ethical and change the API key. + settingsDb.update({ + _id: 'apiKey' + }, { + value: apiKey + }, {}); + } + + showToast('Settings have been saved.'); } /** @@ -203,13 +204,13 @@ function updateSettings() { * @return {Void} */ function toggleTheme(themeValue) { - if (themeValue.checked === true) { - setTheme('dark'); - currentTheme = 'dark'; - } else { - setTheme('light'); - currentTheme = 'light'; - } + if (themeValue.checked === true) { + setTheme('dark'); + currentTheme = 'dark'; + } else { + setTheme('light'); + currentTheme = 'light'; + } } /** @@ -220,122 +221,122 @@ function toggleTheme(themeValue) { * @return {Void} */ function setTheme(option) { - let cssFile; - const currentTheme = document.getElementsByTagName("link").item(1); + let cssFile; + const currentTheme = document.getElementsByTagName("link").item(1); - // Create a link element - const newTheme = document.createElement("link"); - newTheme.setAttribute("rel", "stylesheet"); - newTheme.setAttribute("type", "text/css"); + // Create a link element + const newTheme = document.createElement("link"); + newTheme.setAttribute("rel", "stylesheet"); + newTheme.setAttribute("type", "text/css"); - // Grab the css file to be used. - switch (option) { + // Grab the css file to be used. + switch (option) { case 'light': - cssFile = './style/lightTheme.css'; - document.getElementById('menuText').src = 'icons/textBlack.png'; - document.getElementById('menuIcon').src = 'icons/iconBlack.png'; - document.getElementById('menuButton').style.color = 'black'; - break; + cssFile = './style/lightTheme.css'; + document.getElementById('menuText').src = 'icons/textBlack.png'; + document.getElementById('menuIcon').src = 'icons/iconBlack.png'; + document.getElementById('menuButton').style.color = 'black'; + break; case 'dark': - cssFile = './style/darkTheme.css'; - document.getElementById('menuText').src = 'icons/textColor.png'; - document.getElementById('menuIcon').src = 'icons/iconColor.png'; - document.getElementById('menuButton').style.color = 'white'; - break; + cssFile = './style/darkTheme.css'; + document.getElementById('menuText').src = 'icons/textColor.png'; + document.getElementById('menuIcon').src = 'icons/iconColor.png'; + document.getElementById('menuButton').style.color = 'white'; + break; default: - // Default to the light theme - cssFile = './style/lightTheme.css'; - break; - } - newTheme.setAttribute("href", cssFile); - - // Replace the current theme with the new theme - document.getElementsByTagName("head").item(0).replaceChild(newTheme, currentTheme); -} - -/** -* Import Subscriptions from an OPML file. -* -* @param {string} subFile - The file location of the OPML file. -* -* @return {Void} -*/ -function importOpmlSubs(json){ - if(!json[0]['folder'].includes('YouTube')){ - showToast('Invalid OPML File. Import is unsuccessful.'); - return; - } - - json.forEach((channel) => { - let channelId = channel['xmlurl'].replace('https://www.youtube.com/feeds/videos.xml?channel_id=', ''); - - addSubscription(channelId, false); - }); - window.setTimeout(displaySubs, 1000); - showToast('Subscriptions have been imported!'); - return; -} - -/** -* Import a subscriptions file that the user provides. -* -* @return {Void} -*/ -function importSubscriptions(){ - const appDatabaseFile = localDataStorage + '/subscriptions.db'; - - // Open user's file browser. Only show .db files. - dialog.showOpenDialog({ - properties: ['openFile'], - filters: [ - {name: 'Database File', extensions: ['*']}, - ] - }, function(fileLocation){ - if(typeof(fileLocation) === 'undefined'){ - console.log('Import Aborted'); - return; + // Default to the light theme + cssFile = './style/lightTheme.css'; + break; } - console.log(fileLocation); - let i = fileLocation[0].lastIndexOf('.'); - let fileType = (i < 0) ? '' : fileLocation[0].substr(i); - console.log(fileType); + newTheme.setAttribute("href", cssFile); - /*if (fileType !== '.db'){ - showToast('Incorrect filetype. Import was unsuccessful.'); - return; - }*/ + // Replace the current theme with the new theme + document.getElementsByTagName("head").item(0).replaceChild(newTheme, currentTheme); +} - fs.readFile(fileLocation[0], function(readErr, data){ - if(readErr){ - showToast('Unable to read file. File may be corrupt or have invalid permissions.'); - throw readErr; - } - - if (data.includes(" { + let channelId = channel['xmlurl'].replace('https://www.youtube.com/feeds/videos.xml?channel_id=', ''); - fs.writeFile(appDatabaseFile, data, function(writeErr){ - if(writeErr){ - showToast('Unable to create file. Please check your permissions and try again.'); - throw writeErr; + addSubscription(channelId, false); + }); + window.setTimeout(displaySubs, 1000); + showToast('Subscriptions have been imported!'); + return; +} + +/** + * Import a subscriptions file that the user provides. + * + * @return {Void} + */ +function importSubscriptions() { + const appDatabaseFile = localDataStorage + '/subscriptions.db'; + + // Open user's file browser. Only show .db files. + dialog.showOpenDialog({ + properties: ['openFile'], + filters: [{ + name: 'Database File', + extensions: ['*'] + }, ] + }, function (fileLocation) { + if (typeof (fileLocation) === 'undefined') { + ft.log('Import Aborted'); + return; } - showToast('Susbcriptions have been successfully imported. Please restart FreeTube for the changes to take effect.'); - }); - }) - }); + ft.log('File Location: ', fileLocation); + let i = fileLocation[0].lastIndexOf('.'); + let fileType = (i < 0) ? '' : fileLocation[0].substr(i); + ft.log('File Type: ', fileType); + + /*if (fileType !== '.db'){ + showToast('Incorrect filetype. Import was unsuccessful.'); + return; + }*/ + + fs.readFile(fileLocation[0], function (readErr, data) { + if (readErr) { + showToast('Unable to read file. File may be corrupt or have invalid permissions.'); + throw readErr; + } + + if (data.includes(". + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ @@ -29,30 +29,30 @@ along with FreeTube. If not, see . * @return {Void} */ function addSubscription(channelId, useToast = true) { - console.log(channelId); - // Request YouTube API - youtubeAPI('channels', { - part: 'snippet', - id: channelId, - }, function(data) { - const channelInfo = data['items'][0]['snippet']; - const channelName = channelInfo['title']; - const thumbnail = channelInfo['thumbnails']['high']['url']; + ft.log('Channel ID: ', channelId); + // Request YouTube API + youtubeAPI('channels', { + part: 'snippet', + id: channelId, + }, (data) => { + const channelInfo = data['items'][0]['snippet']; + const channelName = channelInfo['title']; + const thumbnail = channelInfo['thumbnails']['high']['url']; - const channel = { - channelId: channelId, - channelName: channelName, - channelThumbnail: thumbnail, - }; + const channel = { + channelId: channelId, + channelName: channelName, + channelThumbnail: thumbnail, + }; - // Refresh the list of subscriptions on the side navigation bar. - subDb.insert(channel, (err, newDoc) => { - if (useToast) { - showToast('Added ' + channelName + ' to subscriptions.'); - displaySubs(); - } + // Refresh the list of subscriptions on the side navigation bar. + subDb.insert(channel, (err, newDoc) => { + if (useToast) { + showToast('Added ' + channelName + ' to subscriptions.'); + displaySubs(); + } + }); }); - }); } /** @@ -63,13 +63,13 @@ function addSubscription(channelId, useToast = true) { * @return {Void} */ function removeSubscription(channelId) { - subDb.remove({ - channelId: channelId - }, {}, (err, numRemoved) => { - // Refresh the list of subscriptions on the side navigation bar. - displaySubs(); - showToast('Removed channel from subscriptions.'); - }); + subDb.remove({ + channelId: channelId + }, {}, (err, numRemoved) => { + // Refresh the list of subscriptions on the side navigation bar. + displaySubs(); + showToast('Removed channel from subscriptions.'); + }); } /** @@ -78,92 +78,92 @@ function removeSubscription(channelId) { * @return {Void} */ function loadSubscriptions() { - clearMainContainer(); - showToast('Getting Subscriptions. Please wait...'); - const loading = document.getElementById('loading'); + clearMainContainer(); + showToast('Getting Subscriptions. Please wait...'); + const loading = document.getElementById('loading'); - startLoadingAnimation() + startLoadingAnimation(); - let videoList = []; + let videoList = []; - const subscriptions = returnSubscriptions(); + const subscriptions = returnSubscriptions(); - // Welcome to callback hell, we hope you enjoy your stay. - subscriptions.then((results) => { - let channelId = ''; - let videoList = []; + // Welcome to callback hell, we hope you enjoy your stay. + subscriptions.then((results) => { + let channelId = ''; + let videoList = []; - if (results.length > 0) { - let counter = 0; + if (results.length > 0) { + let counter = 0; + + for (let i = 0; i < results.length; i++) { + channelId = results[i]['channelId']; - for (let i = 0; i < results.length; i++) { - channelId = results[i]['channelId']; + youtubeAPI('search', { + part: 'snippet', + channelId: channelId, + type: 'video', + maxResults: 15, + order: 'date', + }, (data) => { - youtubeAPI('search', { - part: 'snippet', - channelId: channelId, - type: 'video', - maxResults: 15, - order: 'date', - }, (data) => { - console.log(data); - videoList = videoList.concat(data.items); - counter++; - if (counter === results.length) { - videoList.sort((a, b) => { - const date1 = Date.parse(a.snippet.publishedAt); - const date2 = Date.parse(b.snippet.publishedAt); + videoList = videoList.concat(data.items); + counter++; + if (counter === results.length) { + videoList.sort((a, b) => { + const date1 = Date.parse(a.snippet.publishedAt); + const date2 = Date.parse(b.snippet.publishedAt); - return date2.valueOf() - date1.valueOf(); + return date2.valueOf() - date1.valueOf(); + }); + + // Render the videos to the application. + createVideoListContainer('Latest Subscriptions:'); + + // The YouTube website limits the subscriptions to 100 before grabbing more so we only show 100 + // to keep the app running at a good speed. + + if (videoList.length < 50) { + let grabDuration = getDuration(videoList.slice(0, 49)); + + grabDuration.then((list) => { + list.items.forEach((video) => { + displayVideo(video); + }); + stopLoadingAnimation(); + }); + } else { + + let finishedList = []; + let firstBatchDuration = getDuration(videoList.slice(0, 49)); + + firstBatchDuration.then((list1) => { + finishedList = finishedList.concat(list1.items); + let secondBatchDuration = getDuration(videoList.slice(50, 99)); + + secondBatchDuration.then((list2) => { + finishedList = finishedList.concat(list2.items); + finishedList.forEach((video) => { + displayVideo(video); + }); + stopLoadingAnimation(); + }); + }); + } + } }); - - // Render the videos to the application. - createVideoListContainer('Latest Subscriptions:'); - - // The YouTube website limits the subscriptions to 100 before grabbing more so we only show 100 - // to keep the app running at a good speed. - if (videoList.length < 50) { - let grabDuration = getDuration(videoList.slice(0, 49)); - - grabDuration.then((list) => { - list.items.forEach((video) => { - displayVideo(video); - }); - stopLoadingAnimation(); - }); - } else { - console.log(videoList); - let finishedList = []; - let firstBatchDuration = getDuration(videoList.slice(0, 49)); - - firstBatchDuration.then((list1) => { - finishedList = finishedList.concat(list1.items); - let secondBatchDuration = getDuration(videoList.slice(50, 99)); - - secondBatchDuration.then((list2) => { - finishedList = finishedList.concat(list2.items); - finishedList.forEach((video) => { - displayVideo(video); - }); - stopLoadingAnimation(); - }); - }); - } - } } - ); - } - } else { - // User has no subscriptions. Display message. - const container = document.getElementById('main'); - stopLoadingAnimation(); + } else { + // User has no subscriptions. Display message. + const container = document.getElementById('main'); + stopLoadingAnimation(); - container.innerHTML = `

Your Subscription list is currently empty. Start adding subscriptions + container.innerHTML = `

Your Subscription list is currently empty. Start adding subscriptions to see them here.

`; - } - }); + } + }); } /** @@ -172,11 +172,11 @@ function loadSubscriptions() { * @return {promise} The list of subscriptions. */ function returnSubscriptions() { - return new Promise((resolve, reject) => { - subDb.find({}, (err, subs) => { - resolve(subs); + return new Promise((resolve, reject) => { + subDb.find({}, (err, subs) => { + resolve(subs); + }); }); - }); } /** @@ -185,31 +185,31 @@ function returnSubscriptions() { * @return {Void} */ function displaySubs() { - const subList = document.getElementById('subscriptions'); + const subList = document.getElementById('subscriptions'); - subList.innerHTML = ''; + subList.innerHTML = ''; - // Sort alphabetically - subDb.find({}).sort({ - channelName: 1 - }).exec((err, subs) => { - subs.forEach((channel) => { - // Grab subscriptions.html to be used as a template. - const subsTemplate = require('./templates/subscriptions.html') - mustache.parse(subsTemplate); - const rendered = mustache.render(subsTemplate, { - channelIcon: channel['channelThumbnail'], - channelName: channel['channelName'], - channelId: channel['channelId'], - }); - // Render template to page. - const subscriptionsHtml = $('#subscriptions').html(); - $('#subscriptions').html(subscriptionsHtml + rendered); + // Sort alphabetically + subDb.find({}).sort({ + channelName: 1 + }).exec((err, subs) => { + subs.forEach((channel) => { + // Grab subscriptions.html to be used as a template. + const subsTemplate = require('./templates/subscriptions.html') + mustache.parse(subsTemplate); + const rendered = mustache.render(subsTemplate, { + channelIcon: channel['channelThumbnail'], + channelName: channel['channelName'], + channelId: channel['channelId'], + }); + // Render template to page. + const subscriptionsHtml = $('#subscriptions').html(); + $('#subscriptions').html(subscriptionsHtml + rendered); + }); }); - }); - // Add onclick function - $('#subscriptions .fa-times').onClick = removeSubscription; + // Add onclick function + $('#subscriptions .fa-times').onClick = removeSubscription; } /** @@ -219,25 +219,25 @@ function displaySubs() { * @return {Void} */ function toggleSubscription(channelId) { - event.stopPropagation(); + event.stopPropagation(); - const checkIfSubscribed = isSubscribed(channelId); - const subscribeButton = document.getElementById('subscribeButton'); + const checkIfSubscribed = isSubscribed(channelId); + const subscribeButton = document.getElementById('subscribeButton'); - checkIfSubscribed.then((results) => { + checkIfSubscribed.then((results) => { - if (results === false) { - if (subscribeButton != null) { - subscribeButton.innerHTML = 'UNSUBSCRIBE'; - } - addSubscription(channelId); - } else { - if (subscribeButton != null) { - subscribeButton.innerHTML = 'SUBSCRIBE'; - } - removeSubscription(channelId); - } - }); + if (results === false) { + if (subscribeButton != null) { + subscribeButton.innerHTML = 'UNSUBSCRIBE'; + } + addSubscription(channelId); + } else { + if (subscribeButton != null) { + subscribeButton.innerHTML = 'SUBSCRIBE'; + } + removeSubscription(channelId); + } + }); } /** @@ -248,15 +248,15 @@ function toggleSubscription(channelId) { * @return {promise} - A boolean value if the channel is currently subscribed or not. */ function isSubscribed(channelId) { - return new Promise((resolve, reject) => { - subDb.find({ - channelId: channelId - }, (err, docs) => { - if (jQuery.isEmptyObject(docs)) { - resolve(false); - } else { - resolve(true); - } + return new Promise((resolve, reject) => { + subDb.find({ + channelId: channelId + }, (err, docs) => { + if (jQuery.isEmptyObject(docs)) { + resolve(false); + } else { + resolve(true); + } + }); }); - }); -} +} \ No newline at end of file diff --git a/src/js/updates.js b/src/js/updates.js index 7e448c9c9..4c66017ff 100644 --- a/src/js/updates.js +++ b/src/js/updates.js @@ -1,45 +1,45 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ - +// import {freeTubeLog} from './events.js'; /* * A file for checking / managing updates */ - const updateChecker = require('github-version-checker'); +const updateChecker = require('github-version-checker'); - const options = { - token: 'USERACCESSTOKEN', // personal access token. Github will not allow commiting the access token, which is why this is blank. - repo: 'freetube', // repository name - owner: 'freetubeapp', // repository owner - currentVersion: require('electron').remote.app.getVersion(), // your app's current version - fetchTags: false // whether to fetch releases or tags - }; +const options = { + token: 'USERACCESSTOKEN', // personal access token. Github will not allow commiting the access token, which is why this is blank. + repo: 'freetube', // repository name + owner: 'freetubeapp', // repository owner + currentVersion: require('electron').remote.app.getVersion(), // your app's current version + fetchTags: false // whether to fetch releases or tags +}; - const openReleasePage = function(){ - shell.openExternal('https://github.com/FreeTubeApp/FreeTube/releases'); - } +const openReleasePage = function () { + shell.openExternal('https://github.com/FreeTubeApp/FreeTube/releases'); +} /*function checkForUpdates() { updateChecker(options, function(error, update) { // callback function if (error){ showToast('There was a problem with checking for updates'); - console.log(error); + freeTubeLog(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); @@ -50,9 +50,9 @@ along with FreeTube. If not, see . }); }*/ -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); - } -}); +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); + } +}); \ No newline at end of file diff --git a/src/js/videos.js b/src/js/videos.js index f31435464..a378cbfe3 100644 --- a/src/js/videos.js +++ b/src/js/videos.js @@ -1,18 +1,18 @@ /* -This file is part of FreeTube. + This file is part of FreeTube. -FreeTube is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -FreeTube is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with FreeTube. If not, see . + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . */ @@ -25,71 +25,71 @@ along with FreeTube. If not, see . * @return {Void} */ function search(nextPageToken = '') { - const query = document.getElementById('search').value; + const query = document.getElementById('search').value; - if (query === '') { - return; - } - - if (nextPageToken === '') { - clearMainContainer(); - startLoadingAnimation(); - } else { - console.log(nextPageToken); - showToast('Fetching results. Please wait...'); - } - - youtubeAPI('search', { - q: query, - part: 'id', - pageToken: nextPageToken, - maxResults: 25, - }, function(data) { - console.log(data); - - let channels = data.items.filter((item) => { - if (item.id.kind === 'youtube#channel') { - return true; - } - }); - - let playlists = data.items.filter((item) => { - if (item.id.kind === 'youtube#playlist') { - return true; - } - }); - - let videos = data.items.filter((item) => { - if (item.id.kind === 'youtube#video') { - return true; - } - }); - - console.log(channels); - console.log(typeof(channels)); - console.log(playlists); - - if(playlists.length > 0){ - //displayPlaylists(playlists); + if (query === '') { + return; } - if(channels.length > 0){ - displayChannels(channels); - } - - let grabDuration = getDuration(videos); - - grabDuration.then((videoList) => { - console.log(videoList); - videoList.items.forEach(displayVideo); - }); - if (nextPageToken === '') { - createVideoListContainer('Search results:'); - stopLoadingAnimation(); + clearMainContainer(); + startLoadingAnimation(); + } else { + ft.log('Next page token: ', nextPageToken); + showToast('Fetching results. Please wait...'); } - addNextPage(data.nextPageToken); - }) + + youtubeAPI('search', { + q: query, + part: 'id', + pageToken: nextPageToken, + maxResults: 25, + }, function (data) { + ft.log('Search Data: ', data); + + let channels = data.items.filter((item) => { + if (item.id.kind === 'youtube#channel') { + return true; + } + }); + + let playlists = data.items.filter((item) => { + if (item.id.kind === 'youtube#playlist') { + return true; + } + }); + + let videos = data.items.filter((item) => { + if (item.id.kind === 'youtube#video') { + return true; + } + }); + + ft.log('Channels: ', channels); + ft.log('Typeof object above (channels) ^^', typeof (channels)); + ft.log('Playlists', playlists); + + if (playlists.length > 0) { + //displayPlaylists(playlists); + } + + if (channels.length > 0) { + displayChannels(channels); + } + + let grabDuration = getDuration(videos); + + grabDuration.then((videoList) => { + ft.log('Video Lists: ', videoList); + videoList.items.forEach(displayVideo); + }); + + if (nextPageToken === '') { + createVideoListContainer('Search results:'); + stopLoadingAnimation(); + } + addNextPage(data.nextPageToken); + }) } /** @@ -100,32 +100,32 @@ function search(nextPageToken = '') { * @return {promise} - The list of videos with the duration included. */ function getDuration(data) { - return new Promise((resolve, reject) => { - let videoIdList = ''; + return new Promise((resolve, reject) => { + let videoIdList = ''; - for (let i = 0; i < data.length; i++) { - if (videoIdList === '') { - if (typeof(data[i]['id']) === 'string') { - videoIdList = data[i]['id']; - } else { - videoIdList = data[i]['id']['videoId']; + for (let i = 0; i < data.length; i++) { + if (videoIdList === '') { + if (typeof (data[i]['id']) === 'string') { + videoIdList = data[i]['id']; + } else { + videoIdList = data[i]['id']['videoId']; + } + } else { + if (typeof (data[i]['id']) === 'string') { + videoIdList = videoIdList + ', ' + data[i]['id']; + } else { + videoIdList = videoIdList + ', ' + data[i]['id']['videoId']; + } + } } - } else { - if (typeof(data[i]['id']) === 'string') { - videoIdList = videoIdList + ', ' + data[i]['id']; - } else { - videoIdList = videoIdList + ', ' + data[i]['id']['videoId']; - } - } - } - youtubeAPI('videos', { - part: 'snippet, contentDetails', - id: videoIdList - }, (data) => { - resolve(data); + youtubeAPI('videos', { + part: 'snippet, contentDetails', + id: videoIdList + }, (data) => { + resolve(data); + }); }); - }); } /** @@ -138,135 +138,135 @@ function getDuration(data) { * @return {Void} */ function displayVideo(video, listType = '') { - const videoSnippet = video.snippet; + const videoSnippet = video.snippet; - const videoDuration = parseVideoDuration(video.contentDetails.duration); - //const videoDuration = '00:00'; + const videoDuration = parseVideoDuration(video.contentDetails.duration); + //const videoDuration = '00:00'; - // Grab the published date for the video and convert to a user readable state. - const dateString = new Date(videoSnippet.publishedAt); - const publishedDate = dateFormat(dateString, "mmm dS, yyyy"); + // Grab the published date for the video and convert to a user readable state. + const dateString = new Date(videoSnippet.publishedAt); + const publishedDate = dateFormat(dateString, "mmm dS, yyyy"); - const searchMenu = $('#videoListContainer').html(); - const videoId = video.id; + const searchMenu = $('#videoListContainer').html(); + const videoId = video.id; - // Include a remove icon in the list if the application is displaying the history list or saved videos. - const deleteHtml = () => { - switch (listType) { - case 'saved': - return `
  • Remove Saved Video
  • `; - case 'history': - return `
  • Remove From History
  • `; + // Include a remove icon in the list if the application is displaying the history list or saved videos. + const deleteHtml = () => { + switch (listType) { + case 'saved': + return `
  • Remove From Favorites
  • `; + case 'history': + return `
  • Remove From History
  • `; + } + }; + + // Includes text if the video is live. + const liveText = (videoSnippet.liveBroadcastContent === 'live') ? 'LIVE NOW' : ''; + const videoListTemplate = require('./templates/videoList.html'); + + mustache.parse(videoListTemplate); + const rendered = mustache.render(videoListTemplate, { + videoId: videoId, + videoThumbnail: videoSnippet.thumbnails.medium.url, + videoTitle: videoSnippet.title, + channelName: videoSnippet.channelTitle, + videoDescription: videoSnippet.description, + channelId: videoSnippet.channelId, + videoDuration: videoDuration, + publishedDate: publishedDate, + liveText: liveText, + deleteHtml: deleteHtml, + }); + + // Apply the render to the page + const nextButton = document.getElementById('getNextPage'); + if (nextButton === null) { + $('#videoListContainer').append(rendered); + } else { + $(rendered).insertBefore('#getNextPage'); } - }; - - // Includes text if the video is live. - const liveText = (videoSnippet.liveBroadcastContent === 'live') ? 'LIVE NOW' : ''; - const videoListTemplate = require('./templates/videoList.html'); - - mustache.parse(videoListTemplate); - const rendered = mustache.render(videoListTemplate, { - videoId: videoId, - videoThumbnail: videoSnippet.thumbnails.medium.url, - videoTitle: videoSnippet.title, - channelName: videoSnippet.channelTitle, - videoDescription: videoSnippet.description, - channelId: videoSnippet.channelId, - videoDuration: videoDuration, - publishedDate: publishedDate, - liveText: liveText, - deleteHtml: deleteHtml, - }); - - // Apply the render to the page - const nextButton = document.getElementById('getNextPage'); - if (nextButton === null) { - $('#videoListContainer').append(rendered); - } else { - $(rendered).insertBefore('#getNextPage'); - } } function displayChannels(channels) { - let channelIds; + let channelIds; - channels.forEach((channel) => { - if (typeof(channelIds) === 'undefined') { - channelIds = channel.id.channelId; - } else { - channelIds = channelIds + ',' + channel.id.channelId; - } - }); - - console.log(channelIds); - - youtubeAPI('channels', { - part: 'snippet,statistics', - id: channelIds, - }, function(data) { - console.log(data); - let items = data['items'].reverse(); - const videoListTemplate = require('./templates/channelList.html'); - - console.log(items); - - items.forEach((item) => { - mustache.parse(videoListTemplate); - let rendered = mustache.render(videoListTemplate, { - channelId: item.id, - channelThumbnail: item.snippet.thumbnails.medium.url, - channelName: item.snippet.title, - channelDescription: item.snippet.description, - subscriberCount: item.statistics.subscriberCount, - videoCount: item.statistics.videoCount, - }); - - $(rendered).insertBefore('#getNextPage'); + channels.forEach((channel) => { + if (typeof (channelIds) === 'undefined') { + channelIds = channel.id.channelId; + } else { + channelIds = channelIds + ',' + channel.id.channelId; + } + }); + + ft.log('Channel IDs: ', channelIds); + + youtubeAPI('channels', { + part: 'snippet,statistics', + id: channelIds, + }, function (data) { + ft.log('Channel Data: ', data); + let items = data['items'].reverse(); + const videoListTemplate = require('./templates/channelList.html'); + + ft.log('Channel Items: ', items); + + items.forEach((item) => { + mustache.parse(videoListTemplate); + let rendered = mustache.render(videoListTemplate, { + channelId: item.id, + channelThumbnail: item.snippet.thumbnails.medium.url, + channelName: item.snippet.title, + channelDescription: item.snippet.description, + subscriberCount: item.statistics.subscriberCount, + videoCount: item.statistics.videoCount, + }); + + $(rendered).insertBefore('#getNextPage'); + }); }); - }); } function displayPlaylists(playlists) { - let playlistIds; + let playlistIds; - playlists.forEach((playlist) => { - if (typeof(playlistIds) === 'undefined') { - playlistIds = playlist.id.playlistId; - } else { - playlistIds = playlistIds + ',' + playlist.id.playlistId; - } - }); - - console.log(playlistIds); - - youtubeAPI('playlists', { - part: 'snippet,contentDetails', - id: playlistIds, - }, function(data) { - console.log(data); - let items = data['items'].reverse(); - const playlistListTemplate = require('./templates/playlistList.html'); - - console.log(items); - - items.forEach((item) => { - let dateString = new Date(item.snippet.publishedAt); - let publishedDate = dateFormat(dateString, "mmm dS, yyyy"); - - mustache.parse(playlistListTemplate); - let rendered = mustache.render(playlistListTemplate, { - channelId: item.snippet.channelId, - channelName: item.snippet.channelTitle, - playlistThumbnail: item.snippet.thumbnails.medium.url, - playlistTitle: item.snippet.title, - playlistDescription: item.snippet.description, - videoCount: item.contentDetails.itemCount, - publishedDate: publishedDate, - }); - - $(rendered).insertBefore('#getNextPage'); + playlists.forEach((playlist) => { + if (typeof (playlistIds) === 'undefined') { + playlistIds = playlist.id.playlistId; + } else { + playlistIds = playlistIds + ',' + playlist.id.playlistId; + } + }); + + ft.log('Playlist IDs: ', playlistIds); + + youtubeAPI('playlists', { + part: 'snippet,contentDetails', + id: playlistIds, + }, function (data) { + ft.log('Playlist Data: ', data); + let items = data['items'].reverse(); + const playlistListTemplate = require('./templates/playlistList.html'); + + ft.log('Playlist Items: ', items); + + items.forEach((item) => { + let dateString = new Date(item.snippet.publishedAt); + let publishedDate = dateFormat(dateString, "mmm dS, yyyy"); + + mustache.parse(playlistListTemplate); + let rendered = mustache.render(playlistListTemplate, { + channelId: item.snippet.channelId, + channelName: item.snippet.channelTitle, + playlistThumbnail: item.snippet.thumbnails.medium.url, + playlistTitle: item.snippet.title, + playlistDescription: item.snippet.description, + videoCount: item.contentDetails.itemCount, + publishedDate: publishedDate, + }); + + $(rendered).insertBefore('#getNextPage'); + }); }); - }); } /** @@ -277,22 +277,22 @@ function displayPlaylists(playlists) { * @return {Void} */ function addNextPage(nextPageToken) { - let oldFetchButton = document.getElementById('getNextPage'); + let oldFetchButton = document.getElementById('getNextPage'); - // Creates the element if it doesn't exist. - if (oldFetchButton === null) { - let fetchButton = document.createElement('div'); - fetchButton.id = 'getNextPage'; - fetchButton.innerHTML = ' Fetch more results...'; + // Creates the element if it doesn't exist. + if (oldFetchButton === null) { + let fetchButton = document.createElement('div'); + fetchButton.id = 'getNextPage'; + fetchButton.innerHTML = ' Fetch more results...'; - $('#videoListContainer').append(fetchButton); - } + $('#videoListContainer').append(fetchButton); + } - // Update the on click method of the button. - $(document).off('click', '#getNextPage'); - $(document).on('click', '#getNextPage', (event) => { - search(nextPageToken); - }); + // Update the on click method of the button. + $(document).off('click', '#getNextPage'); + $(document).on('click', '#getNextPage', (event) => { + search(nextPageToken); + }); } /** @@ -303,33 +303,33 @@ function addNextPage(nextPageToken) { * @param {string} videoId - The video ID of the video to get recommendations from. */ function showVideoRecommendations(videoId) { - youtubeAPI('search', { - part: 'id', - type: 'video', - relatedToVideoId: videoId, - maxResults: 15, - }, function(data) { - let grabDuration = getDuration(data.items); - grabDuration.then((videoList) => { - videoList.items.forEach((video) => { - const snippet = video.snippet; - const videoDuration = parseVideoDuration(video.contentDetails.duration); + youtubeAPI('search', { + part: 'id', + type: 'video', + relatedToVideoId: videoId, + maxResults: 15, + }, function (data) { + let grabDuration = getDuration(data.items); + grabDuration.then((videoList) => { + videoList.items.forEach((video) => { + const snippet = video.snippet; + const videoDuration = parseVideoDuration(video.contentDetails.duration); - const recommTemplate = require('./templates/recommendations.html') - mustache.parse(recommTemplate); - const rendered = mustache.render(recommTemplate, { - videoId: video.id, - videoTitle: snippet.title, - channelName: snippet.channelTitle, - videoThumbnail: snippet.thumbnails.medium.url, - videoDuration: videoDuration, - publishedDate: dateFormat(snippet.publishedAt, "mmm dS, yyyy") + const recommTemplate = require('./templates/recommendations.html') + mustache.parse(recommTemplate); + const rendered = mustache.render(recommTemplate, { + videoId: video.id, + videoTitle: snippet.title, + channelName: snippet.channelTitle, + videoThumbnail: snippet.thumbnails.medium.url, + videoDuration: videoDuration, + publishedDate: dateFormat(snippet.publishedAt, "mmm dS, yyyy") + }); + const recommendationHtml = $('#recommendations').html(); + $('#recommendations').html(recommendationHtml + rendered); + }); }); - const recommendationHtml = $('#recommendations').html(); - $('#recommendations').html(recommendationHtml + rendered); - }); }); - }); } /** @@ -339,50 +339,46 @@ function showVideoRecommendations(videoId) { * @return {Void} */ function parseSearchText(url = '') { - let input; + let input; - if (url === ''){ - input = document.getElementById('search').value; - } - else{ - input = url; - } + if (url === '') { + input = document.getElementById('search').value; + } else { + input = url; + } - if (input === '') { - return; - } + if (input === '') { + return; + } - // The regex to get the video id from a YouTube link. Thanks StackOverflow. - let rx = /^.*(?:(?:(you|hook)tu\.?be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/; + // The regex to get the video id from a YouTube link. Thanks StackOverflow. + let rx = /^.*(?:(?:(you|hook)tu\.?be\/|v\/|vi\/|u\/\w\/|embed\/)|(?:(?:watch)?\?v(?:i)?=|\&v(?:i)?=))([^#\&\?]*).*/; - let match = input.match(rx); + let match = input.match(rx); - console.log(match); - let urlSplit = input.split('/'); - if(match){ - console.log('Video found'); - playVideo(match[2]); - } - else if (urlSplit[3] == 'channel'){ - console.log('channel found'); - goToChannel(urlSplit[4]); - } - else if (urlSplit[3] == 'user'){ - console.log('user found'); - // call api to get the ID and then call goToChannel(id) - youtubeAPI('channels', { - part: 'id', - forUsername: urlSplit[4] - }, (data) => { - console.log(data.items[0].id); - let channelID = data.items[0].id; - goToChannel(channelID); - }); - } - else { - console.log('Video not found'); - search(); - } + ft.log('Video ID: ', match); + let urlSplit = input.split('/'); + if (match) { + ft.log('Video found'); + playVideo(match[2]); + } else if (urlSplit[3] == 'channel') { + ft.log('channel found'); + goToChannel(urlSplit[4]); + } else if (urlSplit[3] == 'user') { + ft.log('user found'); + // call api to get the ID and then call goToChannel(id) + youtubeAPI('channels', { + part: 'id', + forUsername: urlSplit[4] + }, (data) => { + ft.log('Channel Data: ', data.items[0].id); + let channelID = data.items[0].id; + goToChannel(channelID); + }); + } else { + ft.log('Video not found'); + search(); + } } @@ -395,42 +391,42 @@ function parseSearchText(url = '') { * @return {string} - The formated string. Ex: 12:34:56 */ function parseVideoDuration(durationString) { - let match = durationString.match(/PT(\d+H)?(\d+M)?(\d+S)?/); - let duration = ''; + let match = durationString.match(/PT(\d+H)?(\d+M)?(\d+S)?/); + let duration = ''; - match = match.slice(1).map(function(x) { - if (x != null) { - return x.replace(/\D/, ''); + match = match.slice(1).map(function (x) { + if (x != null) { + return x.replace(/\D/, ''); + } + }); + + let hours = (parseInt(match[0]) || 0); + let minutes = (parseInt(match[1]) || 0); + let seconds = (parseInt(match[2]) || 0); + + if (hours != 0) { + duration = hours + ':'; + } else { + duration = minutes + ':'; } - }); - let hours = (parseInt(match[0]) || 0); - let minutes = (parseInt(match[1]) || 0); - let seconds = (parseInt(match[2]) || 0); + if (hours != 0 && minutes < 10) { + duration = duration + '0' + minutes + ':'; + } else if (hours != 0 && minutes > 10) { + duration = duration + minutes + ':'; + } else if (hours != 0 && minutes == 0) { + duration = duration + '00:'; + } - if (hours != 0) { - duration = hours + ':'; - } else { - duration = minutes + ':'; - } + if (seconds == 0) { + duration = duration + '00'; + } else if (seconds < 10) { + duration = duration + '0' + seconds; + } else { + duration = duration + seconds; + } - if (hours != 0 && minutes < 10) { - duration = duration + '0' + minutes + ':'; - } else if (hours != 0 && minutes > 10) { - duration = duration + minutes + ':'; - } else if (hours != 0 && minutes == 0) { - duration = duration + '00:'; - } - - if (seconds == 0) { - duration = duration + '00'; - } else if (seconds < 10) { - duration = duration + '0' + seconds; - } else { - duration = duration + seconds; - } - - return duration; + return duration; } /** @@ -439,38 +435,38 @@ function parseVideoDuration(durationString) { * @return {Void} */ function showMostPopular() { - clearMainContainer(); - startLoadingAnimation(); + clearMainContainer(); + startLoadingAnimation(); - // Get the date of 2 days ago. - var d = new Date(); - d.setDate(d.getDate() - 2); + // Get the date of 2 days ago. + var d = new Date(); + d.setDate(d.getDate() - 2); - // Grab all videos published 2 days ago and after and order them by view count. - // These are the videos that are considered as 'most popular' and is how similar - // Applications grab these. Videos in the 'Trending' tab on YouTube will be different. - // And there is no way to grab those videos. - youtubeAPI('search', { - part: 'id', - order: 'viewCount', - type: 'video', - publishedAfter: d.toISOString(), - maxResults: 50, - }, function(data) { - createVideoListContainer('Most Popular:'); - console.log(data); - let grabDuration = getDuration(data.items); + // Grab all videos published 2 days ago and after and order them by view count. + // These are the videos that are considered as 'most popular' and is how similar + // Applications grab these. Videos in the 'Trending' tab on YouTube will be different. + // And there is no way to grab those videos. + youtubeAPI('search', { + part: 'id', + order: 'viewCount', + type: 'video', + publishedAfter: d.toISOString(), + maxResults: 50, + }, function (data) { + createVideoListContainer('Most Popular:'); + ft.log('Most Popular: ', data); + let grabDuration = getDuration(data.items); - grabDuration.then((videoList) => { - console.log(videoList); - videoList.items.forEach(displayVideo); + grabDuration.then((videoList) => { + ft.log('Video List: ', videoList); + videoList.items.forEach(displayVideo); + }); + stopLoadingAnimation(); }); - stopLoadingAnimation(); - }); } /** - * Create a link of the video to HookTube or YouTube and copy it to the user's clipboard. + * Create a link of the video to Invidious or YouTube and copy it to the user's clipboard. * * @param {string} website - The website to watch the video on. * @param {string} videoId - The video ID of the video to add to the URL @@ -478,10 +474,21 @@ function showMostPopular() { * @return {Void} */ function copyLink(website, videoId) { - // Create the URL and copy to the clipboard. - const url = 'https://' + website + '.com/watch?v=' + videoId; - clipboard.writeText(url); - showToast('URL has been copied to the clipboard'); + // Create the URL and copy to the clipboard. + if (website == "youtube") { + const url = 'https://' + website + '.com/watch?v=' + videoId; + clipboard.writeText(url); + showToast('URL has been copied to the clipboard'); + } + + if (website == "invidious") { + website = "invidio"; + const url = "https://" + website + ".us/watch?v=" + videoId; + clipboard.writeText(url); + showToast('URL has been copied to the clipboard'); + } + + } /** @@ -492,20 +499,20 @@ function copyLink(website, videoId) { * @return {promise} - The HTML of the embeded player */ function getChannelAndPlayer(videoId) { - console.log(videoId); - return new Promise((resolve, reject) => { - youtubeAPI('videos', { - part: 'snippet,player', - id: videoId, - }, function(data) { - let embedHtml = data.items[0].player.embedHtml; - embedHtml = embedHtml.replace('src="', 'src="https:'); - embedHtml = embedHtml.replace('width="480px"', ''); - embedHtml = embedHtml.replace('height="270px"', ''); - embedHtml = embedHtml.replace(/\"/g, '"'); - resolve([embedHtml, data.items[0].snippet.channelId]); + ft.log('Video ID: ', videoId); + return new Promise((resolve, reject) => { + youtubeAPI('videos', { + part: 'snippet,player', + id: videoId, + }, function (data) { + let embedHtml = data.items[0].player.embedHtml; + embedHtml = embedHtml.replace('src="', 'src="https:'); + embedHtml = embedHtml.replace('width="480px"', ''); + embedHtml = embedHtml.replace('height="270px"', ''); + embedHtml = embedHtml.replace(/\"/g, '"'); + resolve([embedHtml, data.items[0].snippet.channelId]); + }); }); - }); } /** @@ -517,68 +524,68 @@ function getChannelAndPlayer(videoId) { * @param {string} video720p - The URL to the 720p video. */ function checkVideoUrls(video480p, video720p) { - const currentQuality = $('#currentQuality').html(); - let buttonEmbed = document.getElementById('qualityEmbed'); + const currentQuality = $('#currentQuality').html(); + let buttonEmbed = document.getElementById('qualityEmbed'); - let valid480 = false; + let valid480 = false; - if (typeof(video480p) !== 'undefined') { - let get480pUrl = fetch(video480p); - get480pUrl.then((status) => { - switch (status.status) { - case 404: - showToast('Found valid URL for 480p, but returned a 404. Video type might be available in the future.'); - $(document).off('click', '#quality480p'); - $(document).on('click', '#quality480p', (event) => { - changeQuality(''); - }); - buttonEmbed.click(); - return; - break; - case 403: - showToast('This video is unavailable in your country.'); - $(document).off('click', '#quality480p'); - $(document).on('click', '#quality480p', (event) => { - changeQuality(''); - }); - return; - break; - default: - console.log('480p is valid'); - if (currentQuality === '720p' && typeof(video720p) === 'undefined') { - changeQuality(video480p); - } - break; - } - }); - } + if (typeof (video480p) !== 'undefined') { + let get480pUrl = fetch(video480p); + get480pUrl.then((status) => { + switch (status.status) { + case 404: + showToast('Found valid URL for 480p, but returned a 404. Video type might be available in the future.'); + $(document).off('click', '#quality480p'); + $(document).on('click', '#quality480p', (event) => { + changeQuality(''); + }); + buttonEmbed.click(); + return; + break; + case 403: + showToast('This video is unavailable in your country.'); + $(document).off('click', '#quality480p'); + $(document).on('click', '#quality480p', (event) => { + changeQuality(''); + }); + return; + break; + default: + ft.log('480p is valid'); + if (currentQuality === '720p' && typeof (video720p) === 'undefined') { + changeQuality(video480p); + } + break; + } + }); + } - if (typeof(video720p) !== 'undefined') { - let get720pUrl = fetch(video720p); - get720pUrl.then((status) => { - switch (status.status) { - case 404: - showToast('Found valid URL for 720p, but returned a 404. Video type might be available in the future.'); - $(document).off('click', '#quality720p'); - $(document).on('click', '#quality720p', (event) => { - changeQuality(''); - }); - if (typeof(valid480) !== 'undefined') { - changeQuality(video480p, '480p'); - } - break; - case 403: - showToast('This video is unavailable in your country.'); - $(document).off('click', '#quality720p'); - $(document).on('click', '#quality720p', (event) => { - changeQuality(''); - }); - return; - break; - default: - console.log('720p is valid'); - break; - } - }); - } -} + if (typeof (video720p) !== 'undefined') { + let get720pUrl = fetch(video720p); + get720pUrl.then((status) => { + switch (status.status) { + case 404: + showToast('Found valid URL for 720p, but returned a 404. Video type might be available in the future.'); + $(document).off('click', '#quality720p'); + $(document).on('click', '#quality720p', (event) => { + changeQuality(''); + }); + if (typeof (valid480) !== 'undefined') { + changeQuality(video480p, '480p'); + } + break; + case 403: + showToast('This video is unavailable in your country.'); + $(document).off('click', '#quality720p'); + $(document).on('click', '#quality720p', (event) => { + changeQuality(''); + }); + return; + break; + default: + ft.log('720p is valid'); + break; + } + }); + } +} \ No newline at end of file diff --git a/src/js/youtubeApi.js b/src/js/youtubeApi.js index 26659169c..6d1fa2ab5 100644 --- a/src/js/youtubeApi.js +++ b/src/js/youtubeApi.js @@ -1,3 +1,22 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + + + /** * List a YouTube HTTP API resource. * @@ -9,33 +28,33 @@ */ function youtubeAPI(resource, params, success) { - params.key = apiKey; + params.key = apiKey; - if (useTor) { - tor.request('https://www.googleapis.com/youtube/v3/' + resource + '?' + $.param(params), function(err, res, body) { - if (!err && res.statusCode == 200) { - success(JSON.parse(body)); - } else { - showToast('Unable to connect to the Tor network. Check the help page if you\'re having trouble setting up your node.'); - console.log(err); - console.log(res); - console.log(body); - stopLoadingAnimation(); - } - }); - } else { - $.getJSON( - 'https://www.googleapis.com/youtube/v3/' + resource, - params, - success - ).fail((xhr, textStatus, error) => { - showToast('There was an error calling the YouTube API.'); - console.log(error); - console.log(xhr); - console.log(textStatus); - stopLoadingAnimation(); - }); - } + if (useTor) { + tor.request('https://www.googleapis.com/youtube/v3/' + resource + '?' + $.param(params), function (err, res, body) { + if (!err && res.statusCode == 200) { + success(JSON.parse(body)); + } else { + showToast('Unable to connect to the Tor network. Check the help page if you\'resss having trouble setting up your node.'); + ft.log('Tor Error: ', err); + ft.log('Tor Error (Result): ', res); + ft.log('Tor Error (body): ', body); + stopLoadingAnimation(); + } + }); + } else { + $.getJSON( + 'https://www.googleapis.com/youtube/v3/' + resource, + params, + success + ).fail((xhr, textStatus, error) => { + showToast('There was an error calling the YouTube API.'); + ft.log('YT API Error: ', error); + ft.log('YT API Error - XHR: ', xhr); + ft.log('YT API Error - Text Status: ', textStatus); + stopLoadingAnimation(); + }); + } } @@ -50,19 +69,19 @@ function youtubeAPI(resource, params, success) { */ function youtubedlGetInfo(videoId, callback) { - let url = 'https://youtube.com/watch?v=' + videoId; - let options = ['--all-subs', '--write-subs']; + let url = 'https://youtube.com/watch?v=' + videoId; + let options = ['--all-subs', '--write-subs']; - ytdl.getInfo(url, options, function(err, info) { - if (err) { - showToast(err.message); - stopLoadingAnimation(); - console.log(err); - console.log(info); - return; - } + ytdl.getInfo(url, options, function (err, info) { + if (err) { + showToast(err.message); + stopLoadingAnimation(); + ft.log('Error getting video download info: ', err.message); + ft.log('Error getting video download info: ', info); + return; + } - console.log('Success'); - callback(info); - }); -} + ft.log('Success'); + callback(info); + }); +} \ No newline at end of file diff --git a/src/style/channel.css b/src/style/channel.css index 244629e00..caf2d7986 100644 --- a/src/style/channel.css +++ b/src/style/channel.css @@ -1,45 +1,62 @@ -.channelViewBanner{ - width: 100%; - max-height: 200px; - margin-bottom: 30px; +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + +.channelViewBanner { + width: 100%; + max-height: 200px; + margin-bottom: 30px; } -.channelViewImage{ - float: left; - width: 100px; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; +.channelViewImage { + float: left; + width: 100px; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; } -.channelViewTitle{ - height: 100px; - margin-left: 100px; +.channelViewTitle { + height: 100px; + margin-left: 100px; } -.channelViewName{ - font-weight: bold; - font-size: 25px; - margin-left: 20px; - position: relative; - top: 20px; +.channelViewName { + font-weight: bold; + font-size: 25px; + margin-left: 20px; + position: relative; + top: 20px; } -.channelViewSubs{ - margin-left: 20px; - margin-top: 20px; - position: relative; - top: 20px; +.channelViewSubs { + margin-left: 20px; + margin-top: 20px; + position: relative; + top: 20px; } -.channelSubButton{ - float: right; - width: 125px; - height: 50px; - line-height: 50px; - text-align: center; - cursor: pointer; +.channelSubButton { + float: right; + width: 125px; + height: 50px; + line-height: 50px; + text-align: center; + cursor: pointer; } -.channelViewDescription{ - white-space: pre-line; +.channelViewDescription { + white-space: pre-line; } diff --git a/src/style/darkTheme.css b/src/style/darkTheme.css index 01ad71c4f..fd9d45528 100644 --- a/src/style/darkTheme.css +++ b/src/style/darkTheme.css @@ -1,3 +1,20 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + ::-webkit-scrollbar { height: 12px; width: 12px; @@ -14,54 +31,218 @@ background: #262626; } -body{background-color: #212121;} -input[type=text] {color: #EEEEEE;} -.sk-cube-grid .sk-cube {background-color: #f44336;} -.searchBar ::-webkit-input-placeholder {color: #E0E0E0;} -.topNav{background-color: #262626; -webkit-box-shadow: 0px -4px 20px 0px rgba(0,0,0,0.75);} -.logo{color: #f44336;} -.searchBar input{border-bottom: 1px solid #ddd;} -.searchButton{color: #E0E0E0;} -.jumpToInput{border-bottom: 1px solid #E0E0E0;} -.message{color: #757575;} -.videoDelete{color: white;} -.channelViewImage{border: 0px solid white;} -.channelViewName{color: #EEEEEE;} -.channelViewSubs{color: #BDBDBD;} -.channelViewDescription{color: #E0E0E0;} -.channelSubButton{color: #E0E0E0; background-color: #f44336;} -.videoTitle{color: #EEEEEE;} -.channelName{color: #E0E0E0;} -.videoDescription{color: #E0E0E0;} -.statistics{background-color: #424242; color: #EEEEEE;} -.views{color: #E0E0E0;} -.details{background-color: #424242; color: #EEEEEE;} -.playerSubButton{color: #E0E0E0; background-color: #f44336;} -.smallButton{color: #E0E0E0; background-color: #757575;} -.recommendDate{color: #E0E0E0;} -.settingsButton {color: #BDBDBD; background-color: #424242;} -.qualityTypes{color: #E0E0E0; background-color: #757575;} -.speedTypes{color: #E0E0E0; background-color: #757575;} -.unsaved{color: #E0E0E0;} -.double-bounce1, .double-bounce2 {background-color: #f44336;} -.videoOptions ul {background-color: #262626; color: white;} -.videoOptions li:hover {background-color: #262626;} -.videoOptions a {color: white;} +body { + background-color: #212121; +} -#main{color: #EEEEEE;} -#main hr{border-bottom: 1px solid #212121;} -#subscriptions img{border: 0px solid white;} -#sideNav{background-color: #262626; color: #E0E0E0; -webkit-box-shadow: 4px -2px 51px -6px rgba(0,0,0,0.75);} -#sideNav hr{background-color: #f44336;} -#sideNav li:hover{background-color: #212121;} -#channelIcon{border: 0px solid white;} -#channelName{color: #E0E0E0;} -#publishDate{color: #E0E0E0;} -#description{color: #E0E0E0;} -#showComments{background-color: #757575; color: #E0E0E0;} -#recommendations{color: #EEEEEE;} -#videoListContainer{color: #EEEEEE;} -#toast{background-color: #616161; color: white;} -#confirmFunction{background-color: #616161; color: white;} -#getNextPage{background-color: #616161} -#comments{background-color: #424242;} +input[type=text] { + color: #EEEEEE; +} + +.sk-cube-grid .sk-cube { + background-color: #f44336; +} + +.searchBar ::-webkit-input-placeholder { + color: #E0E0E0; +} + +.topNav { + background-color: #262626; + -webkit-box-shadow: 0px -4px 20px 0px rgba(0, 0, 0, 0.75); +} + +.logo { + color: #f44336; +} + +.searchBar input { + border-bottom: 1px solid #ddd; +} + +.searchButton { + color: #E0E0E0; +} + +.jumpToInput { + border-bottom: 1px solid #E0E0E0; +} + +.message { + color: #757575; +} + +.videoDelete { + color: white; +} + +.channelViewImage { + border: 0px solid white; +} + +.channelViewName { + color: #EEEEEE; +} + +.channelViewSubs { + color: #BDBDBD; +} + +.channelViewDescription { + color: #E0E0E0; +} + +.channelSubButton { + color: #E0E0E0; + background-color: #f44336; +} + +.videoTitle { + color: #EEEEEE; +} + +.channelName { + color: #E0E0E0; +} + +.videoDescription { + color: #E0E0E0; +} + +.statistics { + background-color: #424242; + color: #EEEEEE; +} + +.views { + color: #E0E0E0; +} + +.details { + background-color: #424242; + color: #EEEEEE; +} + +.playerSubButton { + color: #E0E0E0; + background-color: #f44336; +} + +.smallButton { + color: #E0E0E0; + background-color: #757575; +} + +.recommendDate { + color: #E0E0E0; +} + +.settingsButton { + color: #BDBDBD; + background-color: #424242; +} + +.qualityTypes { + color: #E0E0E0; + background-color: #757575; +} + +.speedTypes { + color: #E0E0E0; + background-color: #757575; +} + +.unsaved { + color: #E0E0E0; +} + +.double-bounce1, +.double-bounce2 { + background-color: #f44336; +} + +.videoOptions ul { + background-color: #262626; + color: white; +} + +.videoOptions li:hover { + background-color: #262626; +} + +.videoOptions a { + color: white; +} + +#main { + color: #EEEEEE; +} + +#main hr { + border-bottom: 1px solid #212121; +} + +#subscriptions img { + border: 0px solid white; +} + +#sideNav { + background-color: #262626; + color: #E0E0E0; + -webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75); +} + +#sideNav hr { + background-color: #f44336; +} + +#sideNav li:hover { + background-color: #212121; +} + +#channelIcon { + border: 0px solid white; +} + +#channelName { + color: #E0E0E0; +} + +#publishDate { + color: #E0E0E0; +} + +#description { + color: #E0E0E0; +} + +#showComments { + background-color: #757575; + color: #E0E0E0; +} + +#recommendations { + color: #EEEEEE; +} + +#videoListContainer { + color: #EEEEEE; +} + +#toast { + background-color: #616161; + color: white; +} + +#confirmFunction { + background-color: #616161; + color: white; +} + +#getNextPage { + background-color: #616161 +} + +#comments { + background-color: #424242; +} diff --git a/src/style/lightTheme.css b/src/style/lightTheme.css index 9c45b1386..4d1e82328 100644 --- a/src/style/lightTheme.css +++ b/src/style/lightTheme.css @@ -1,3 +1,20 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + ::-webkit-scrollbar { height: 12px; width: 12px; @@ -14,43 +31,167 @@ background: white; } -body{background-color: #e0e0e0;} -.sk-cube-grid .sk-cube {background-color: #f44336;} -.searchBar ::-webkit-input-placeholder {color: #ddd;} -.topNav{background-color: #f44336; -webkit-box-shadow: 0px -4px 32px 0px rgba(0, 0, 0, 0.75);} -.searchBar input{border-bottom: 1px solid #ddd;} -.searchButton{color: black;} -.jumpToInput{border-bottom: 1px solid #757575;} -.message{color: #757575;} -.videoDelete{color: black;} -.channelViewImage{border: 0px solid #000000;} -.channelViewSubs{color: #757575;} -.channelSubButton{color: #616161; background-color: #eeeeee;} -.videoTitle{color: #000000;} -.channelName{color: #424242;} -.videoDescription{color: #424242;} -.statistics{background-color: white;} -.views{color: #424242;} -.details{background-color: white;} -.playerSubButton{color: #616161; background-color: #eeeeee;} -.smallButton{color: #616161; background-color: #eeeeee;} -.recommendDate{color: #616161;} -.settingsButton {color: #424242; background-color: #BDBDBD;} -.qualityTypes{background-color: #eeeeee;} -.speedTypes{background-color: #eeeeee;} -.unsaved{color: #616161;} -.double-bounce1, .double-bounce2 {background-color: #f44336;} -.videoOptions ul {background-color: #f5f5f5;} -.videoOptions li:hover {background-color: #e0e0e0;} -.videoOptions a {color: black;} +body { + background-color: #e0e0e0; +} -#subscriptions img{border: 0px solid #000000;} -#sideNav{background-color: white; -webkit-box-shadow: 4px -2px 51px -6px rgba(0,0,0,0.75);} -#sideNav hr{background-color: #f44336;} -#sideNav li:hover{background-color: #e0e0e0;} -#channelIcon{border: 0px solid #000000;} -#showComments{background-color: #eeeeee;} -#toast{background-color: #212121; color: #f5f5f5;;} -#confirmFunction{background-color: #f5f5f5;} -#getNextPage{background-color: #f5f5f5;} -#comments{background: #eee;} +.sk-cube-grid .sk-cube { + background-color: #f44336; +} + +.searchBar ::-webkit-input-placeholder { + color: #ddd; +} + +.topNav { + background-color: #f44336; + -webkit-box-shadow: 0px -4px 32px 0px rgba(0, 0, 0, 0.75); +} + +.searchBar input { + border-bottom: 1px solid #ddd; +} + +.searchButton { + color: black; +} + +.jumpToInput { + border-bottom: 1px solid #757575; +} + +.message { + color: #757575; +} + +.videoDelete { + color: black; +} + +.channelViewImage { + border: 0px solid #000000; +} + +.channelViewSubs { + color: #757575; +} + +.channelSubButton { + color: #616161; + background-color: #eeeeee; +} + +.videoTitle { + color: #000000; +} + +.channelName { + color: #424242; +} + +.videoDescription { + color: #424242; +} + +.statistics { + background-color: white; +} + +.views { + color: #424242; +} + +.details { + background-color: white; +} + +.playerSubButton { + color: #616161; + background-color: #eeeeee; +} + +.smallButton { + color: #616161; + background-color: #eeeeee; +} + +.recommendDate { + color: #616161; +} + +.settingsButton { + color: #424242; + background-color: #BDBDBD; +} + +.qualityTypes { + background-color: #eeeeee; +} + +.speedTypes { + background-color: #eeeeee; +} + +.unsaved { + color: #616161; +} + +.double-bounce1, +.double-bounce2 { + background-color: #f44336; +} + +.videoOptions ul { + background-color: #f5f5f5; +} + +.videoOptions li:hover { + background-color: #e0e0e0; +} + +.videoOptions a { + color: black; +} + +#subscriptions img { + border: 0px solid #000000; +} + +#sideNav { + background-color: white; + -webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75); +} + +#sideNav hr { + background-color: #f44336; +} + +#sideNav li:hover { + background-color: #e0e0e0; +} + +#channelIcon { + border: 0px solid #000000; +} + +#showComments { + background-color: #eeeeee; +} + +#toast { + background-color: #212121; + color: #f5f5f5; + ; +} + +#confirmFunction { + background-color: #f5f5f5; +} + +#getNextPage { + background-color: #f5f5f5; +} + +#comments { + background: #eee; +} diff --git a/src/style/loading.css b/src/style/loading.css index 2439ef045..7daf4a13c 100644 --- a/src/style/loading.css +++ b/src/style/loading.css @@ -1,45 +1,71 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + /* * Thanks to @tobiasahlin for the loading animation. * Find it here: http://tobiasahlin.com/spinkit/ * Twitter: https://twitter.com/tobiasahlin */ -.spinner { - width: 40px; - height: 40px; - position: relative; - margin: 100px auto; +.spinner { + width: 40px; + height: 40px; + + position: relative; + margin: 100px auto; } -.double-bounce1, .double-bounce2 { - width: 100%; - height: 100%; - border-radius: 50%; - opacity: 0.6; - position: absolute; - top: 0; - left: 0; +.double-bounce1, +.double-bounce2 { + width: 100%; + height: 100%; + border-radius: 50%; + opacity: 0.6; + position: absolute; + top: 0; + left: 0; - -webkit-animation: sk-bounce 2.0s infinite ease-in-out; - animation: sk-bounce 2.0s infinite ease-in-out; + -webkit-animation: sk-bounce 2.0s infinite ease-in-out; + animation: sk-bounce 2.0s infinite ease-in-out; } .double-bounce2 { - -webkit-animation-delay: -1.0s; - animation-delay: -1.0s; + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; } @-webkit-keyframes sk-bounce { - 0%, 100% { -webkit-transform: scale(0.0) } - 50% { -webkit-transform: scale(1.0) } + 0%, + 100% { + -webkit-transform: scale(0.0) + } + 50% { + -webkit-transform: scale(1.0) + } } @keyframes sk-bounce { - 0%, 100% { - transform: scale(0.0); - -webkit-transform: scale(0.0); - } 50% { - transform: scale(1.0); - -webkit-transform: scale(1.0); - } + 0%, + 100% { + transform: scale(0.0); + -webkit-transform: scale(0.0); + } + 50% { + transform: scale(1.0); + -webkit-transform: scale(1.0); + } } diff --git a/src/style/main.css b/src/style/main.css index b01fe0acf..3433a027f 100644 --- a/src/style/main.css +++ b/src/style/main.css @@ -1,373 +1,393 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + @font-face { font-family: Roboto; src: url(Roboto-Regular.ttf); } body { - font-family: 'Roboto', sans-serif; + font-family: 'Roboto', sans-serif; } input { - box-sizing: border-box; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - outline: none; - width: 100%; - padding: 7px; - border: none; - background: transparent; - margin-bottom: 10px; - font: 16px; - height: 45px; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + outline: none; + width: 100%; + padding: 7px; + border: none; + background: transparent; + margin-bottom: 10px; + font: 16px; + height: 45px; } a { - color: #2196F3; + color: #2196F3; } .center { - text-align: center; - margin: 0 auto; + text-align: center; + margin: 0 auto; } .topNav { - width: 100%; - height: 60px; - line-height: 60px; - position: fixed; - top: 0; - left: 0; - z-index: 1; + width: 100%; + height: 60px; + line-height: 60px; + position: fixed; + top: 0; + left: 0; + z-index: 1; } .topNav span { - display: inline-block; - vertical-align: middle; - line-height: normal; + display: inline-block; + vertical-align: middle; + line-height: normal; } #menuButton { - cursor: pointer; - font-weight: bold; - font-size: 20px; - margin-left: 20px; - position: relative; - top: 3px; + cursor: pointer; + font-weight: bold; + font-size: 20px; + margin-left: 20px; + position: relative; + top: 3px; } #menuIcon { - width: 25px; - position: relative; - top: 15px; - right: 120px; - float: right; + width: 25px; + position: relative; + top: 15px; + right: 120px; + float: right; } #menuText { - width: 100px; - position: relative; - top: 5px; - left: 10px; - float: right; + width: 100px; + position: relative; + top: 5px; + left: 10px; + float: right; } .searchBar { - position: absolute; - right: 135px; - top: 0; - width: 50%; + position: absolute; + right: 135px; + top: 0; + width: 50%; } .searchBar input { - width: 90%; + width: 90%; } .searchButton { - text-decoration: none; + text-decoration: none; } #sideNav { - height: 100vh; - width: 250px; - overflow-y: auto; - position: fixed; - left: 0; - top: 0px; - -webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75); + height: 100vh; + width: 250px; + overflow-y: auto; + position: fixed; + left: 0; + top: 0px; + -webkit-box-shadow: 4px -2px 51px -6px rgba(0, 0, 0, 0.75); } #sideNav hr { - width: 95%; - height: 1px; - border: 0; + width: 95%; + height: 1px; + border: 0; } #sideNav ul { - list-style-type: none; + list-style-type: none; } #sideNav li { - padding: 20px; - width: 205px; - position: relative; - right: 50px; - cursor: pointer; - -webkit-transition: background 0.2s ease-out; - -moz-transition: background 0.2s ease-out; - -o-transition: background 0.2s ease-out; - transition: background 0.2s ease-out; + padding: 20px; + width: 205px; + position: relative; + right: 50px; + cursor: pointer; + -webkit-transition: background 0.2s ease-out; + -moz-transition: background 0.2s ease-out; + -o-transition: background 0.2s ease-out; + transition: background 0.2s ease-out; } #sideNav li:hover { - -moz-transition: background 0.2s ease-in; - -o-transition: background 0.2s ease-in; - transition: background 0.2s ease-in; + -moz-transition: background 0.2s ease-in; + -o-transition: background 0.2s ease-in; + transition: background 0.2s ease-in; } #sideNavDisabled { - height: 100vh; - width: 250px; - position: fixed; - left: 0; - top: 0px; - z-index: 1; - margin-top: 85px; - display: none; + height: 100vh; + width: 250px; + position: fixed; + left: 0; + top: 0px; + z-index: 1; + margin-top: 85px; + display: none; } .sideNavContainer { - margin-top: 85px; + margin-top: 85px; } #subscriptions img { - float: left; - width: 40px; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; - position: relative; - top: -12px; - margin-right: 5px; + float: left; + width: 40px; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; + position: relative; + top: -12px; + margin-right: 5px; } #subscriptions .fa-times { - float: right; - margin-right: 5px; + float: right; + margin-right: 5px; } #subscriptions li { - font-size: 11px; + font-size: 11px; } .message { - text-align: center; + text-align: center; } .videoDelete { - float: right; - cursor: pointer; + float: right; + cursor: pointer; } #loading { - width: 75%; - height: 20%; - margin: auto; - position: absolute; - top: 0; - left: 5; - bottom: 0; - right: 0; - display: none; + width: 75%; + height: 20%; + margin: auto; + position: absolute; + top: 0; + left: 5; + bottom: 0; + right: 0; + display: none; } .settingsInput { - width: 50%; - border-bottom: 1px solid #616161; + width: 50%; + border-bottom: 1px solid #616161; } .settingsButton { - padding: 10px; - display: inline-block; - cursor: pointer; - margin: 5px; - -webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); - -moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); - box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + padding: 10px; + display: inline-block; + cursor: pointer; + margin: 5px; + -webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); } .settingsSubmit { - padding: 15px; - color: #212121; - background-color: #f44336; - cursor: pointer; - width: 150px; - -webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); - -moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); - box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + padding: 15px; + color: #212121; + background-color: #f44336; + cursor: pointer; + width: 150px; + -webkit-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); + box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.75); } .help { - margin: 30px; + margin: 30px; } .live { - font-size: 12px; - height: 20px; - text-align: center; - width: 57px; - position: relative; - left: 284px; - color: #f44336; - bottom: 15px; - line-height: 10px; + font-size: 12px; + height: 20px; + text-align: center; + width: 57px; + position: relative; + left: 284px; + color: #f44336; + bottom: 15px; + line-height: 10px; } -#toast{ - min-width: 400px; - height: 50px; - position: fixed; - bottom: 20px; - right: 20px; - padding: 10px; - text-align: center; - font-size: 17px; - line-height: 50px; - opacity: 0; - z-index: 1; - visibility: hidden; - -webkit-transition: opacity 0.5s ease-in-out; - -moz-transition: opacity 0.5s ease-in-out; - -ms-transition: opacity 0.5s ease-in-out; - -o-transition: opacity 0.5s ease-in-out; +#toast { + min-width: 400px; + height: 50px; + position: fixed; + bottom: 20px; + right: 20px; + padding: 10px; + text-align: center; + font-size: 17px; + line-height: 50px; + opacity: 0; + z-index: 1; + visibility: hidden; + -webkit-transition: opacity 0.5s ease-in-out; + -moz-transition: opacity 0.5s ease-in-out; + -ms-transition: opacity 0.5s ease-in-out; + -o-transition: opacity 0.5s ease-in-out; } -.closeToast{ - font-size: 15px; - position: absolute; - top: 5px; - right: 10px; - cursor: pointer; +.closeToast { + font-size: 15px; + position: absolute; + top: 5px; + right: 10px; + cursor: pointer; } -#confirmFunction{ - position: fixed; - top: 50%; - left: 30%; - width: 800px; - height: 65px; - font-weight: bold; - line-height: 65px; - visibility: hidden; - z-index: 1; - -webkit-box-shadow: 5px 5px 15px -5px rgba(0,0,0,0.75); - -moz-box-shadow: 5px 5px 15px -5px rgba(0,0,0,0.75); - box-shadow: 5px 5px 15px -5px rgba(0,0,0,0.75); +#confirmFunction { + position: fixed; + top: 50%; + left: 30%; + width: 800px; + height: 65px; + font-weight: bold; + line-height: 65px; + visibility: hidden; + z-index: 1; + -webkit-box-shadow: 5px 5px 15px -5px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 5px 5px 15px -5px rgba(0, 0, 0, 0.75); + box-shadow: 5px 5px 15px -5px rgba(0, 0, 0, 0.75); } -#confirmMessage{ - margin-left: 15px; +#confirmMessage { + margin-left: 15px; } -.confirmButton{ - position: absolute; - top: 0px; - cursor: pointer; +.confirmButton { + position: absolute; + top: 0px; + cursor: pointer; } -#confirmYes{ - right: 90px; - color: #2196f3; +#confirmYes { + right: 90px; + color: #2196f3; } -#confirmNo{ - right: 20px; +#confirmNo { + right: 20px; } -#getNextPage{ - width: 100%; - height: 45px; - line-height: 45px; - text-align: center; - cursor: pointer; +#getNextPage { + width: 100%; + height: 45px; + line-height: 45px; + text-align: center; + cursor: pointer; } -#comments{ - display:none; - padding:1em; - margin-bottom: 1em; +#comments { + display: none; + padding: 1em; + margin-bottom: 1em; } -.saved{color: #FFEB3B;} +.saved { + color: #FFEB3B; +} /* Thanks to Guus Lieben for the Material Design Switch */ .switch-input { - display: none; + display: none; } .switch-label { - position: relative; - display: inline-block; - min-width: 112px; - cursor: pointer; - font-weight: 500; - text-align: left; - margin: 16px; - padding: 16px 0 16px 44px; + position: relative; + display: inline-block; + min-width: 112px; + cursor: pointer; + font-weight: 500; + text-align: left; + margin: 16px; + padding: 16px 0 16px 44px; } -.switch-label:before, .switch-label:after { - content: ""; - position: absolute; - margin: 0; - outline: 0; - top: 50%; - -ms-transform: translate(0, -50%); - -webkit-transform: translate(0, -50%); - transform: translate(0, -50%); - -webkit-transition: all 0.3s ease; - transition: all 0.3s ease; +.switch-label:before, +.switch-label:after { + content: ""; + position: absolute; + margin: 0; + outline: 0; + top: 50%; + -ms-transform: translate(0, -50%); + -webkit-transform: translate(0, -50%); + transform: translate(0, -50%); + -webkit-transition: all 0.3s ease; + transition: all 0.3s ease; } .switch-label:before { - left: 1px; - width: 34px; - height: 14px; - background-color: #9E9E9E; - border-radius: 8px; + left: 1px; + width: 34px; + height: 14px; + background-color: #9E9E9E; + border-radius: 8px; } .switch-label:after { - left: 0; - width: 20px; - height: 20px; - background-color: #FAFAFA; - border-radius: 50%; - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.14), 0 2px 2px 0 rgba(0, 0, 0, 0.098), 0 1px 5px 0 rgba(0, 0, 0, 0.084); + left: 0; + width: 20px; + height: 20px; + background-color: #FAFAFA; + border-radius: 50%; + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.14), 0 2px 2px 0 rgba(0, 0, 0, 0.098), 0 1px 5px 0 rgba(0, 0, 0, 0.084); } .switch-label .toggle--on { - display: none; + display: none; } .switch-label .toggle--off { - display: inline-block; + display: inline-block; } .switch-input:checked+.switch-label:before { - background-color: #90CAF9; + background-color: #90CAF9; } .switch-input:checked+.switch-label:after { - background-color: #2196F3; - -ms-transform: translate(80%, -50%); - -webkit-transform: translate(80%, -50%); - transform: translate(80%, -50%); + background-color: #2196F3; + -ms-transform: translate(80%, -50%); + -webkit-transform: translate(80%, -50%); + transform: translate(80%, -50%); } .switch-input:checked+.switch-label .toggle--on { - display: inline-block; + display: inline-block; } .switch-input:checked+.switch-label .toggle--off { - display: none; + display: none; } diff --git a/src/style/player.css b/src/style/player.css index 6f4bd1817..fa55f1904 100644 --- a/src/style/player.css +++ b/src/style/player.css @@ -1,338 +1,356 @@ +/* + This file is part of FreeTube. + + FreeTube is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FreeTube is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FreeTube. If not, see . +*/ + iframe { - width: 100%; - height: 41.25vw; + width: 100%; + height: 41.25vw; } #main { - margin-top: 80px; - margin-left: 250px; + margin-top: 80px; + margin-left: 250px; } .video { - width: 95%; - max-width: 1000px; - height: 145px; - padding: 15px; - overflow: hidden; + width: 95%; + max-width: 1000px; + height: auto; + padding: 15px; + overflow: hidden; } .videoThumbnail { - width: 275px; - height: 160px; - float: left; - cursor: pointer; + width: 275px; + height: 160px; + float: left; + cursor: pointer; } -.videoThumbnail img{ - width: 100%; +.videoThumbnail img { + width: 100%; } .channelThumbnail { - width: 140px; - height: 140px; - float: left; - cursor: pointer; - position: relative; - left: 60px; + width: 140px; + height: 140px; + float: left; + cursor: pointer; + position: relative; + left: 60px; } -.channelThumbnail img{ - width: 100%; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; +.channelThumbnail img { + width: 100%; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; } .videoOptions { - float: right; - width: 50px; + float: right; + width: 50px; } .videoOptions i { - text-align: right; - width: 50px; - cursor: pointer; + text-align: right; + width: 50px; + cursor: pointer; } .videoOptions ul { - width: 90px; - font-size: 12px; - position: relative; - right: 90px; - bottom: 10px; - list-style-type: none; - display: none; - -webkit-box-shadow: 4px 4px 33px -7px rgba(0,0,0,0.75); - cursor: pointer; + + width: 90px; + font-size: 12px; + position: relative; + right: 90px; + bottom: 10px; + list-style-type: none; + display: none; + -webkit-box-shadow: 4px 4px 33px -7px rgba(0, 0, 0, 0.75); + cursor: pointer; + z-index: 10; } .videoOptions li { - width: 110px; - position: relative; - right: 40px; - padding: 10px; - -webkit-transition: background 0.2s ease-out; - -moz-transition: background 0.2s ease-out; - -o-transition: background 0.2s ease-out; - transition: background 0.2s ease-out; + width: 110px; + position: relative; + right: 40px; + padding: 10px; + -webkit-transition: background 0.2s ease-out; + -moz-transition: background 0.2s ease-out; + -o-transition: background 0.2s ease-out; + transition: background 0.2s ease-out; } .videoOptions li:hover { - -moz-transition: background 0.2s ease-in; - -o-transition: background 0.2s ease-in; - transition: background 0.2s ease-in; + -moz-transition: background 0.2s ease-in; + -o-transition: background 0.2s ease-in; + transition: background 0.2s ease-in; } .videoOptions a { - text-decoration: none; + text-decoration: none; } .videoTitle { - font-weight: bold; - margin-left: 285px; - margin-top: 5px; - cursor: pointer; + font-weight: bold; + margin-left: 285px; + margin-top: 5px; + cursor: pointer; } .channelName { - margin-left: 285px; - font-size: 14px; - cursor: pointer; + margin-left: 285px; + font-size: 14px; + cursor: pointer; } .videoDescription { - margin-left: 285px; - font-size: 13px; - cursor: pointer; - height: 45px; - overflow: hidden; + margin-left: 285px; + font-size: 13px; + cursor: pointer; + height: 45px; + overflow: hidden; } .videoDuration { - display: inline-block; - float: right; - position: relative; - bottom: 36px; - color: white; - background-color: black; - opacity: 0.7; - padding: 2px; - font-size: 13px; - text-align: right; + float: right; + position: relative; + bottom: 36px; + color: white; + background-color: black; + opacity: 0.7; + padding: 2px; + font-size: 13px; + text-align: right; } .videoPlayer { - width: 100%; + width: 100%; } .statistics { - padding: 20px; - padding-bottom: 45px; + padding: 20px; + padding-bottom: 45px; } .title { - font-weight: bold; - font-size: 25px; + font-weight: bold; + font-size: 25px; } .views { - margin-top: -10px; - float: left; + margin-top: -10px; + float: left; } .details { - padding: 15px; + padding: 15px; } .likeContainer { - width: 300px; - float: right; + width: 300px; + float: right; } .likes { - float: left; - font-size: 12px; + float: left; + font-size: 12px; } .dislikes { - float: right; - font-size: 12px; + float: right; + font-size: 12px; } .dislikeBar { - background-color: #9E9E9E; - width: 300px; - height: 5px; - margin-bottom: 5px; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; + background-color: #9E9E9E; + width: 300px; + height: 5px; + margin-bottom: 5px; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; } .likeBar { - height: 5px; - background-color: #2196F3; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; + height: 5px; + background-color: #2196F3; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; } #channelIcon { - float: left; - width: 80px; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; - cursor: pointer; + float: left; + width: 80px; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; + cursor: pointer; } #comments .line { - clear: both; - height: 1px; - background: #d8d8d8; + clear: both; + height: 1px; + background: #d8d8d8; } .userIcon { - float: left; - width: 48px; - border-radius: 200px 200px 200px 200px; - -webkit-border-radius: 200px 200px 200px 200px; - cursor: pointer; + float: left; + width: 48px; + border-radius: 200px 200px 200px 200px; + -webkit-border-radius: 200px 200px 200px 200px; + cursor: pointer; } #channelName { - font-weight: bold; - margin-left: 95px; - font-size: 16px; - cursor: pointer; + font-weight: bold; + margin-left: 95px; + font-size: 16px; + cursor: pointer; } #publishDate { - margin-left: 95px; - font-size: 13px; - margin-top: -10px; + margin-left: 95px; + font-size: 13px; + margin-top: -10px; } #description { - white-space: pre-line; - max-height: 200px; - overflow-y: auto; + white-space: pre-line; + max-height: 200px; + overflow-y: auto; } .playerSubButton { - float: right; - width: 125px; - height: 50px; - line-height: 50px; - text-align: center; - margin-top: -65px; - cursor: pointer; + float: right; + width: 125px; + height: 50px; + line-height: 50px; + text-align: center; + margin-top: -65px; + cursor: pointer; } .smallButton { - float: right; - height: 30px; - font-size: 10px; - line-height: 30px; - text-align: center; - margin-right: 5px; - padding-left: 15px; - padding-right: 15px; - cursor: pointer; + float: right; + height: 30px; + font-size: 10px; + line-height: 30px; + text-align: center; + margin-right: 5px; + padding-left: 15px; + padding-right: 15px; + cursor: pointer; } .videoQuality { - width: 42px; + width: 42px; } .videoQuality:hover .qualityTypes { - visibility: visible; + visibility: visible; } .qualityTypes { - visibility: hidden; - width: 72px; - position: relative; - bottom: 10px; - right: 15px; + visibility: hidden; + width: 72px; + position: relative; + bottom: 10px; + right: 15px; } .qualityTypes ul { - list-style-type: none; - position: relative; - right: 24px; + list-style-type: none; + position: relative; + right: 24px; } .qualityTypes ul li { - width: 72px; - position: relative; - right: 15px; + width: 72px; + position: relative; + right: 15px; } .videoSpeed { - width: 42px; + width: 42px; } .videoSpeed:hover .speedTypes { - visibility: visible; + visibility: visible; } .speedTypes { - visibility: hidden; - width: 72px; - position: relative; - bottom: 10px; - right: 15px; + visibility: hidden; + width: 72px; + position: relative; + bottom: 10px; + right: 15px; } .speedTypes ul { - list-style-type: none; - position: relative; - right: 24px; + list-style-type: none; + position: relative; + right: 24px; } .speedTypes ul li { - width: 72px; - position: relative; - right: 15px; + width: 72px; + position: relative; + right: 15px; } #showComments { - text-align: center; - height: 40px; - line-height: 40px; - margin-top: 15px; - margin-bottom: 15px; + text-align: center; + height: 40px; + line-height: 40px; + margin-top: 15px; + margin-bottom: 15px; } #recommendations { - width: 100%; + width: 100%; } .recommendVideo { - cursor: pointer; - height: 150px; + cursor: pointer; + height: 150px; } .recommendThumbnail { - width: 250px; - height: 145px; - float: left; + width: 250px; + height: 145px; + float: left; } -.recommendThumbnail img{ - width: 100%; +.recommendThumbnail img { + width: 100%; } .recommendTitle { - font-size: 16px; - font-weight: bold; - margin-left: 260px; + font-size: 16px; + font-weight: bold; + margin-left: 260px; } .recommendChannel { - margin-left: 260px; - font-size: 14px; - margin-top: -10px; + margin-left: 260px; + font-size: 14px; + margin-top: -10px; } .recommendDate { - margin-left: 260px; - font-size: 11px; + margin-left: 260px; + font-size: 11px; } diff --git a/src/style/videoList.css b/src/style/videoList.css index 791c4aca5..4d34f765f 100644 --- a/src/style/videoList.css +++ b/src/style/videoList.css @@ -1,6 +1,8 @@ -.videoListContainer{width: 100%;} +.videoListContainer { + width: 100%; +} -.videoListContainer hr{ +.videoListContainer hr { width: 95%; height: 1px; border: 0; diff --git a/src/templates/about.html b/src/templates/about.html index c0c985d28..9ffe52f73 100644 --- a/src/templates/about.html +++ b/src/templates/about.html @@ -1,11 +1,28 @@ + +
    - -

    {{versionNumber}} Beta

    -

      FreeTubeApp@protonmail.com

    -

    This software is FOSS and released under the GNU Public License v3+.

    -

    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 Riot / Matrix Server. Please check the rules before joining.

    -

    Looking for help? Check out our Wiki page.

    -

    Check out our Firefox extension!

    + +

    {{versionNumber}} Beta

    +

      FreeTubeApp@protonmail.com

    +

    This software is FOSS and released under the GNU Public License v3+.

    +

    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 Riot / Matrix Server. Please check the rules before joining.

    +

    Looking for help? Check out our Wiki page.

    +

    Check out our Firefox extension!

    diff --git a/src/templates/channelList.html b/src/templates/channelList.html index ba50395a5..b96b869a9 100644 --- a/src/templates/channelList.html +++ b/src/templates/channelList.html @@ -1,9 +1,26 @@ + +
    -
    - -
    -

    {{channelName}}

    -

    {{subscriberCount}} subscribers - {{videoCount}} videos

    -

    {{channelDescription}}

    +
    + +
    +

    {{channelName}}

    +

    {{subscriberCount}} subscribers - {{videoCount}} videos

    +

    {{channelDescription}}


    diff --git a/src/templates/channelView.html b/src/templates/channelView.html index 9b4642a85..689075bec 100644 --- a/src/templates/channelView.html +++ b/src/templates/channelView.html @@ -1,21 +1,38 @@ + +
    - - {{channelName}} -
    - {{subCount}} Subscribers -
    - {{subButtonText}} -
    + + {{channelName}} +
    + {{subCount}} Subscribers +
    + {{subButtonText}} +


    - {{{channelDescription}}} + {{{channelDescription}}}


    -

    Latest Uploads

    +

    Latest Uploads

    diff --git a/src/templates/comments.html b/src/templates/comments.html index 0aab6394c..8ab0d524e 100644 --- a/src/templates/comments.html +++ b/src/templates/comments.html @@ -1,14 +1,31 @@ + + {{#comments}} -
    -
    - +
    +
    + +
    +
    +

    {{authorDisplayName}}

    +

    {{textOriginal}}

    +

    {{publishedAt}}

    +
    -
    -

    {{authorDisplayName}}

    -

    {{textOriginal}}

    -

    {{publishedAt}}

    -
    -
    -
    -
    +
    +
    {{/comments}} diff --git a/src/templates/miniPlayer.html b/src/templates/miniPlayer.html index 3fb4d2892..a75c79550 100644 --- a/src/templates/miniPlayer.html +++ b/src/templates/miniPlayer.html @@ -1,15 +1,35 @@ + + Freetube Mini-Player {{{videoHtml}}} diff --git a/src/templates/player.html b/src/templates/player.html index 84bd05131..f79889853 100644 --- a/src/templates/player.html +++ b/src/templates/player.html @@ -1,82 +1,100 @@ + +
    -
    - MINI PLAYER -
    -
    - {{videoQuality}} -
    -
      -
    • 480p
    • -
    • 720p
    • -
    • EMBED
    • -
    +
    + MINI PLAYER
    -
    -
    - 1x -
    -
      -
    • 0.25x
    • -
    • 0.5x
    • -
    • 0.75x
    • -
    • 1x
    • -
    • 1.25x
    • -
    • 1.5x
    • -
    • 1.75x
    • -
    • 2x
    • -
    +
    + {{videoQuality}} +
    +
      +
    • 480p
    • +
    • 720p
    • +
    • EMBED
    • +
    +
    -
    -
    - {{savedText}} -
    -
    - COPY YOUTUBE LINK -
    - -
    - OPEN IN YOUTUBE +
    + 1x +
    +
      +
    • 0.25x
    • +
    • 0.5x
    • +
    • 0.75x
    • +
    • 1x
    • +
    • 1.25x
    • +
    • 1.5x
    • +
    • 1.75x
    • +
    • 2x
    • +
    +
    -
    -
    - COPY HOOKTUBE LINK -
    - -
    - OPEN IN HOOKTUBE +
    + {{savedText}}
    -
    -
    -

    {{videoTitle}}

    -

    {{videoViews}} views

    -
    -
    -
    -
    +
    + COPY YOUTUBE LINK +
    + +
    + OPEN IN YOUTUBE +
    +
    +
    + COPY INVIDIOUS LINK +
    + +
    + OPEN IN INVIDIOUS +
    +
    +
    +

    {{videoTitle}}

    +

    {{videoViews}} views

    +
    +
    +
    +
    +
    + {{videoDislikes}}
    - {{videoDislikes}} -
    - -

    {{channelName}}

    -

    Published on {{publishedDate}}

    -
    {{isSubscribed}}
    -

    -
    - {{{description}}} -
    + +

    {{channelName}}

    +

    Published on {{publishedDate}}

    +
    {{isSubscribed}}
    +
    +
    +
    + {{{description}}} +
    - Show Comments (Max of 100) + Show Comments (Max of 100)
    - Recommendations + Recommendations
    diff --git a/src/templates/playerWindow.html b/src/templates/playerWindow.html index c117f7032..c68e212a5 100644 --- a/src/templates/playerWindow.html +++ b/src/templates/playerWindow.html @@ -1,94 +1,112 @@ + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - Freetube Player - + position: relative; + margin: 0px auto; + } + + #loading { + width: 100%; + height: 0%; + } + + -
    -
    -
    -
    +
    +
    +
    +
    +
    -
    -
    - Would you like to perform the function? -
    Yes
    -
    No
    -
    -
    - - -
    -
    - - -
    +
    + + +
    +
    + + +   + +
    +
    diff --git a/src/templates/playlistList.html b/src/templates/playlistList.html index 27334424c..195c5ace9 100644 --- a/src/templates/playlistList.html +++ b/src/templates/playlistList.html @@ -1,10 +1,27 @@ + +
    -
    - -
    -

    {{playlistTitle}}

    -

    {{channelName}} - {{publishedDate}}

    -

    {{playlistDescription}}

    -

    VIEW FULL PLAYLIST ({{videoCount}} videos)

    +
    + +
    +

    {{playlistTitle}}

    +

    {{channelName}} - {{publishedDate}}

    +

    {{playlistDescription}}

    +

    VIEW FULL PLAYLIST ({{videoCount}} videos)


    diff --git a/src/templates/recommendations.html b/src/templates/recommendations.html index a253a25d0..4eeb1cc04 100644 --- a/src/templates/recommendations.html +++ b/src/templates/recommendations.html @@ -1,10 +1,27 @@ + +
    -
    - -

    {{videoDuration}}

    -
    -

    {{videoTitle}}

    -

    {{channelName}}

    -

    {{publishedDate}}

    +
    + +

    {{videoDuration}}

    +
    +

    {{videoTitle}}

    +

    {{channelName}}

    +

    {{publishedDate}}


    diff --git a/src/templates/settings.html b/src/templates/settings.html index a9e4f178d..5665e70f2 100644 --- a/src/templates/settings.html +++ b/src/templates/settings.html @@ -1,35 +1,54 @@ + +

    Settings

    - -
    - -
    - - - - + +
    + +
    + + + +
    -
    - IMPORT SUBSCRIPTIONS -
    -
    - EXPORT SUBSCRIPTIONS -
    +
    + IMPORT SUBSCRIPTIONS +
    +
    + EXPORT SUBSCRIPTIONS +
    -

    +
    +
    -
    - CLEAR HISTORY -
    -
    - CLEAR SAVED VIDEOS -
    -
    - CLEAR SUBSCRIPTIONS -
    +
    + CLEAR HISTORY +
    +
    + CLEAR SAVED VIDEOS +
    +
    + CLEAR SUBSCRIPTIONS +
    -

    +
    +
    - SAVE SETTINGS + SAVE SETTINGS
    diff --git a/src/templates/subscriptions.html b/src/templates/subscriptions.html index fe185ac1b..f00caab37 100644 --- a/src/templates/subscriptions.html +++ b/src/templates/subscriptions.html @@ -1,5 +1,20 @@ +
  • - - {{channelName}} - + {{channelName}} +
  • diff --git a/src/templates/video.html b/src/templates/video.html index 289ee60e2..3934b034c 100644 --- a/src/templates/video.html +++ b/src/templates/video.html @@ -1,4 +1,20 @@ + + diff --git a/src/templates/videoList.html b/src/templates/videoList.html index 9b545c52b..de22a342b 100644 --- a/src/templates/videoList.html +++ b/src/templates/videoList.html @@ -1,21 +1,42 @@ + +
    -
    - - -
    -
    - -

    {{videoDuration}}

    -
    -

    {{videoTitle}}

    -

    {{channelName}} - {{publishedDate}}

    -

    {{videoDescription}}

    -

    {{liveText}}

    +
    + + +
    +
    + +

    {{videoDuration}}

    +
    +

    {{videoTitle}}

    +

    {{channelName}} - {{publishedDate}}

    +

    {{videoDescription}}

    +

    {{liveText}}