├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── .stylintrc
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── _config.yml
├── certs
├── my_private_key.pvk
├── my_signing_key.pfx
└── my_test_certificate.cer
├── docs
├── LICENSE
├── README.md
├── index.html
└── src
│ ├── css
│ └── index.css
│ └── img
│ ├── logo-512x512.png
│ └── logo-qtube.svg
├── package-lock.json
├── package.json
├── quasar.conf.js
├── renovate.json
├── src-electron
├── icons
│ ├── icon.icns
│ ├── icon.ico
│ └── linux-512x512.png
└── main-process
│ ├── auto-updater
│ └── auto-updater.js
│ ├── electron-main.dev.js
│ ├── electron-main.js
│ └── server
│ ├── modules
│ ├── index.js
│ └── manipulate-files
│ │ └── index.js
│ └── server.js
├── src
├── App.vue
├── assets
│ ├── logo-qtube-horizontal.svg
│ ├── logo-qtube.svg
│ ├── quasar-logo-full.svg
│ └── sad.svg
├── components
│ ├── .gitkeep
│ └── videoPlayer.vue
├── css
│ ├── app.styl
│ └── themes
│ │ ├── common.variables.styl
│ │ ├── variables.ios.styl
│ │ └── variables.mat.styl
├── i18n
│ ├── en-us
│ │ └── index.js
│ └── index.js
├── index.template.html
├── layouts
│ └── default.vue
├── pages
│ ├── 404.vue
│ ├── index.vue
│ ├── musics.vue
│ ├── player.vue
│ └── videos.vue
├── plugins
│ ├── .gitkeep
│ ├── axios.js
│ ├── i18n.js
│ └── video-player.js
├── router
│ ├── index.js
│ └── routes.js
├── statics
│ ├── darkrola.jpeg
│ ├── icons
│ │ ├── apple-icon-152x152-.png
│ │ ├── apple-icon-152x152.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── icon-128x128-.png
│ │ ├── icon-128x128.png
│ │ ├── icon-192x192-.png
│ │ ├── icon-192x192.png
│ │ ├── icon-256x256.png
│ │ ├── icon-256x256asd.png
│ │ ├── icon-256x256beta.png
│ │ ├── icon-384x384-.png
│ │ ├── icon-384x384.png
│ │ ├── icon-512x512-.png
│ │ ├── icon-512x512.png
│ │ ├── ms-icon-144x144-.png
│ │ └── ms-icon-144x144.png
│ └── quasar-logo.png
└── store
│ ├── index.js
│ └── module-example
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── mutations.js
│ └── state.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env", {
5 | "modules": false,
6 | "loose": false,
7 | "useBuiltIns": "usage"
8 | }
9 | ],
10 | [
11 | "@babel/preset-stage-2", {
12 | "modules": true,
13 | "loose": false,
14 | "useBuiltIns": true,
15 | "decoratorsLegacy": true
16 | }
17 | ]
18 | ],
19 | "plugins": [
20 | [
21 | "@babel/transform-runtime", {
22 | "polyfill": false,
23 | "regenerator": false
24 | }
25 | ]
26 | ],
27 | "comments": true
28 | }
29 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /dist
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | parser: 'babel-eslint',
5 | sourceType: 'module'
6 | },
7 | env: {
8 | browser: true
9 | },
10 | extends: [
11 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
12 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
13 | 'plugin:vue/essential',
14 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
15 | 'standard'
16 | ],
17 | // required to lint *.vue files
18 | plugins: [
19 | 'vue'
20 | ],
21 | globals: {
22 | 'ga': true, // Google Analytics
23 | 'cordova': true,
24 | '__statics': true
25 | },
26 | // add your custom rules here
27 | 'rules': {
28 | // allow async-await
29 | 'generator-star-spacing': 'off',
30 |
31 | // allow paren-less arrow functions
32 | 'arrow-parens': 0,
33 | 'one-var': 0,
34 |
35 | 'import/first': 0,
36 | 'import/named': 2,
37 | 'import/namespace': 2,
38 | 'import/default': 2,
39 | 'import/export': 2,
40 | 'import/extensions': 0,
41 | 'import/no-unresolved': 0,
42 | 'import/no-extraneous-dependencies': 0,
43 |
44 | // allow debugger during development
45 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .quasar
2 | .DS_Store
3 | .thumbs.db
4 | node_modules
5 | /dist
6 | /src-cordova/platforms
7 | /src-cordova/plugins
8 | /src-cordova/www
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # Editor directories and files
14 | .idea
15 | .vscode
16 | *.suo
17 | *.ntvs*
18 | *.njsproj
19 | *.sln
20 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | plugins: [
5 | // to edit target browsers: use "browserslist" field in package.json
6 | require('autoprefixer')
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.stylintrc:
--------------------------------------------------------------------------------
1 | {
2 | "blocks": "never",
3 | "brackets": "never",
4 | "colons": "never",
5 | "colors": "always",
6 | "commaSpace": "always",
7 | "commentSpace": "always",
8 | "cssLiteral": "never",
9 | "depthLimit": false,
10 | "duplicates": true,
11 | "efficient": "always",
12 | "extendPref": false,
13 | "globalDupe": true,
14 | "indentPref": 2,
15 | "leadingZero": "never",
16 | "maxErrors": false,
17 | "maxWarnings": false,
18 | "mixed": false,
19 | "namingConvention": false,
20 | "namingConventionStrict": false,
21 | "none": "never",
22 | "noImportant": false,
23 | "parenSpace": "never",
24 | "placeholder": false,
25 | "prefixVarsWithDollar": "always",
26 | "quotePref": "single",
27 | "semicolons": "never",
28 | "sortOrder": false,
29 | "stackedProperties": "never",
30 | "trailingWhitespace": "never",
31 | "universal": "never",
32 | "valid": true,
33 | "zeroUnits": "never",
34 | "zIndexNormalize": false
35 | }
36 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributor's Guide
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a
11 | build.
12 | 2. Update the README.md with details of changes to the interface, this includes new environment
13 | variables, exposed ports, useful file locations and container parameters.
14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this
15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
17 | do not have permission to do that, you may request the second reviewer to merge it for you.
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 qtube
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Qtube
2 | This Application used for download YouTube videos and it's built with with Quasar and Electron
3 |
4 | ## Installation
5 | ```bash
6 | $ git clone https://github.com/iagocavalcante/qtube.git
7 | $ cd qtube
8 | $ npm install
9 | $ npm run build
10 | ```
11 |
12 | ## Contributing
13 |
14 | Any type of contribution is welcome, here are some examples of how you may contribute to this project:
15 |
16 | Before starting the contribution, read our [contributing guide](https://github.com/iagocavalcante/qtube/blob/master/CONTRIBUTING.md) and let's build a better antd together.
17 |
18 | ## Reference
19 |
20 | [For your reference](https://iagocavalcante.github.io/qtube/)
21 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-dinky
--------------------------------------------------------------------------------
/certs/my_private_key.pvk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/certs/my_private_key.pvk
--------------------------------------------------------------------------------
/certs/my_signing_key.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/certs/my_signing_key.pfx
--------------------------------------------------------------------------------
/certs/my_test_certificate.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/certs/my_test_certificate.cer
--------------------------------------------------------------------------------
/docs/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2018 Marcos Paulo Sarges Rolim
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Site Quasar App
2 |
3 | This site uses [bootstrap 4.1.3](https://getbootstrap.com/docs/4.1/getting-started/introduction/)
4 |
5 | ## Contributing
6 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
7 | Please make sure to update tests as appropriate.
8 |
9 | ## Licence
10 |
11 | [MIT](https://opensource.org/licenses/MIT)
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
14 |
16 |
17 |
18 | QTube
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
Application built with Quasar and Electron
32 |
33 |
34 |
35 |
36 |
Last release
38 |
All releases
39 |
40 |
41 |
42 |
43 |
44 |
45 |
How to contribute?
46 |
Before starting the contribution, make a Fork in the project.
47 |
60 |
61 | - $ git clone https://github.com/iagocavalcante/qtube.git
62 | - $ cd qtube
63 | - $ npm install
64 | - # The construction process can be time consuming due to
65 | the download of the Quasar and Electron
66 | - $ npm run build
67 |
68 |
69 |
70 |
71 |
72 |
73 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/docs/src/css/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=K2D');
2 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono');
3 | .main-content {
4 | background-image: linear-gradient(to bottom, #D98656, #CC2E2F);
5 | background-repeat: no-repeat;
6 | padding: 120px 0;
7 | }
8 | .container {
9 | color: aliceblue;
10 | font-family: 'Roboto Mono', monospace;
11 | }
12 | .img-fluid{
13 | width:40%;
14 | }
15 |
16 | .header {
17 | background-color: #fff;
18 | padding: 40px;
19 | text-align: center;
20 | }
21 |
22 | .header .logo img {
23 | max-width: 333px;
24 | }
25 |
26 | .titulos{
27 | font-family: 'K2D', sans-serif;
28 | text-align: center;
29 | margin-bottom: 10px;
30 | display: block;
31 | }
32 |
33 | section {
34 | text-align: center;
35 | }
36 |
37 | .card {
38 | color: black;
39 | margin: 0 auto;
40 | border-radius: 10px;
41 | }
42 |
43 | .fa-file-download {
44 | font-size: 2rem;
45 | }
46 |
47 | .init ul{
48 | list-style: none;
49 | }
50 |
51 | footer .container {
52 | text-align: left;
53 | }
54 |
55 | .fa-heart {
56 | color: red;
57 | }
58 |
59 | .footer {
60 | background-color: #8e0a0a;
61 | }
62 |
63 | .rodape {
64 | list-style: none;
65 | margin-bottom: 0;
66 | text-align: center;
67 | padding: 20px 0;
68 | }
69 |
70 | .rodape a {
71 | color: #f0f8ff;
72 | transition: .5s;
73 | }
74 |
75 | .rodape a:hover {
76 | color: #afa5b1;
77 | }
78 |
--------------------------------------------------------------------------------
/docs/src/img/logo-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/docs/src/img/logo-512x512.png
--------------------------------------------------------------------------------
/docs/src/img/logo-qtube.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qtube",
3 | "version": "0.1.159",
4 | "description": "App to copy link and paste, download from youtube",
5 | "productName": "QTube",
6 | "cordovaId": "br.com.qtube.app",
7 | "author": "Iago Cavalcante ",
8 | "repository": "https://github.com/iagocavalcante/qtube",
9 | "private": false,
10 | "scripts": {
11 | "lint": "eslint --ext .js,.vue src",
12 | "test": "echo \"No test specified\" && exit 0",
13 | "publish": "node_modules/.bin/build --win -p always"
14 | },
15 | "dependencies": {
16 | "axios": "0.19.2",
17 | "body-parser": "1.19.0",
18 | "cors": "2.8.5",
19 | "electron-log": "4.0.6",
20 | "electron-squirrel-startup": "1.0.0",
21 | "electron-store": "6.0.0",
22 | "electron-updater": "4.2.2",
23 | "express": "4.17.1",
24 | "fluent-ffmpeg": "2.1.2",
25 | "request": "2.88.2",
26 | "video.js": "7.6.6",
27 | "vue-i18n": "8.20.0",
28 | "vue-video-player": "5.0.2",
29 | "ytdl-core": "3.1.2"
30 | },
31 | "devDependencies": {
32 | "babel-eslint": "10.0.3",
33 | "devtron": "1.4.0",
34 | "electron": "9.1.2",
35 | "electron-builder": "22.8.0",
36 | "electron-debug": "3.0.1",
37 | "electron-devtools-installer": "3.1.1",
38 | "electron-packager": "14.2.1",
39 | "eslint": "7.6.0",
40 | "eslint-config-standard": "14.1.1",
41 | "eslint-friendly-formatter": "4.0.1",
42 | "eslint-loader": "3.0.3",
43 | "eslint-plugin-import": "2.20.1",
44 | "eslint-plugin-node": "11.0.0",
45 | "eslint-plugin-promise": "4.2.1",
46 | "eslint-plugin-standard": "4.0.1",
47 | "eslint-plugin-vue": "6.2.1",
48 | "quasar-cli": "0.17.26",
49 | "strip-ansi": "6.0.0"
50 | },
51 | "engines": {
52 | "node": ">= 8.9.0",
53 | "npm": ">= 5.6.0",
54 | "yarn": ">= 1.6.0"
55 | },
56 | "browserslist": [
57 | "> 1%",
58 | "last 2 versions",
59 | "not ie <= 10"
60 | ]
61 | }
62 |
--------------------------------------------------------------------------------
/quasar.conf.js:
--------------------------------------------------------------------------------
1 | // Configuration for your app
2 |
3 | module.exports = function (ctx) {
4 | return {
5 | // app plugins (/src/plugins)
6 | plugins: [
7 | // 'i18n',
8 | 'axios',
9 | 'video-player'
10 | ],
11 | css: [
12 | 'app.styl'
13 | ],
14 | extras: [
15 | ctx.theme.mat ? 'roboto-font' : null,
16 | 'material-icons' // optional, you are not bound to it
17 | // 'ionicons',
18 | // 'mdi',
19 | // 'fontawesome'
20 | ],
21 | supportIE: false,
22 | build: {
23 | scopeHoisting: true,
24 | vueRouterMode: 'history',
25 | // vueCompiler: true,
26 | gzip: true,
27 | // analyze: true,
28 | // extractCSS: false,
29 | extendWebpack (cfg) {
30 | cfg.module.rules.push({
31 | enforce: 'pre',
32 | test: /\.(js|vue)$/,
33 | loader: 'eslint-loader',
34 | exclude: /(node_modules|quasar)/
35 | })
36 | }
37 | },
38 | devServer: {
39 | // https: true,
40 | // port: 8080,
41 | open: true // opens browser window automatically
42 | },
43 | // framework: 'all' --- includes everything; for dev only!
44 | framework: {
45 | components: [
46 | 'QLayout',
47 | 'QLayoutHeader',
48 | 'QLayoutDrawer',
49 | 'QPageContainer',
50 | 'QPage',
51 | 'QToolbar',
52 | 'QToolbarTitle',
53 | 'QBtn',
54 | 'QIcon',
55 | 'QList',
56 | 'QListHeader',
57 | 'QItem',
58 | 'QItemMain',
59 | 'QItemSide',
60 | 'QTabs',
61 | 'QTab',
62 | 'QTabPane',
63 | 'QRouteTab',
64 | 'QInput',
65 | 'QField',
66 | 'QBtnDropdown',
67 | 'QCard',
68 | 'QCardTitle',
69 | 'QCardMain',
70 | 'QCardMedia',
71 | 'QCardSeparator',
72 | 'QCardActions',
73 | 'QItemTile',
74 | 'QAjaxBar',
75 | 'QTooltip',
76 | 'QSpinnerHourglass',
77 | 'QVideo'
78 | ],
79 | directives: [
80 | 'Ripple'
81 | ],
82 | // Quasar plugins
83 | plugins: [
84 | 'Notify'
85 | ],
86 | // iconSet: ctx.theme.mat ? 'material-icons' : 'ionicons'
87 | // i18n: 'pt-Br' // Quasar language
88 | },
89 | // animations: 'all' --- includes all animations
90 | animations: [
91 | ],
92 | pwa: {
93 | // workboxPluginMode: 'InjectManifest',
94 | // workboxOptions: {},
95 | manifest: {
96 | // name: 'Quasar App',
97 | // short_name: 'Quasar-PWA',
98 | // description: 'Best PWA App in town!',
99 | display: 'standalone',
100 | orientation: 'portrait',
101 | background_color: '#ffffff',
102 | theme_color: '#027be3',
103 | icons: [
104 | {
105 | 'src': 'statics/icons/icon-128x128.png',
106 | 'sizes': '128x128',
107 | 'type': 'image/png'
108 | },
109 | {
110 | 'src': 'statics/icons/icon-192x192.png',
111 | 'sizes': '192x192',
112 | 'type': 'image/png'
113 | },
114 | {
115 | 'src': 'statics/icons/icon-256x256.png',
116 | 'sizes': '256x256',
117 | 'type': 'image/png'
118 | },
119 | {
120 | 'src': 'statics/icons/icon-384x384.png',
121 | 'sizes': '384x384',
122 | 'type': 'image/png'
123 | },
124 | {
125 | 'src': 'statics/icons/icon-512x512.png',
126 | 'sizes': '512x512',
127 | 'type': 'image/png'
128 | }
129 | ]
130 | }
131 | },
132 | cordova: {
133 | // id: 'org.cordova.quasar.app'
134 | },
135 | electron: {
136 | bundler: 'builder', // or 'packager'
137 | extendWebpack (cfg) {
138 | // do something with Electron process Webpack cfg
139 | },
140 | packager: {
141 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
142 |
143 | // OS X / Mac App Store
144 | // appBundleId: '',
145 | // appCategoryType: '',
146 | // osxSign: '',
147 | // protocol: 'myapp://path',
148 |
149 | // Window only
150 | // win32metadata: { ... }
151 | },
152 | builder: {
153 | // https://www.electron.build/configuration/configuration
154 | appId: 'qtube',
155 | publish: {
156 | provider: 'github',
157 | owner: 'iagocavalcante',
158 | repo: 'qtube'
159 | },
160 | // squirrelWindows: {
161 | // remoteReleases: 'https://api.github.com/repos/iagocavalcante/qtube/releases/latest'
162 | // },
163 | win: {
164 | // certificateFile: './certs/my_signing_key.pfx',
165 | // certificatePassword: '',
166 | target: 'nsis'
167 | }
168 | }
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src-electron/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src-electron/icons/icon.icns
--------------------------------------------------------------------------------
/src-electron/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src-electron/icons/icon.ico
--------------------------------------------------------------------------------
/src-electron/icons/linux-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src-electron/icons/linux-512x512.png
--------------------------------------------------------------------------------
/src-electron/main-process/auto-updater/auto-updater.js:
--------------------------------------------------------------------------------
1 | const os = require('os')
2 | import { app, autoUpdater, dialog } from 'electron'
3 | const version = app.getVersion()
4 | const platform = os.platform() + '_' + os.arch() // usually returns darwin_64
5 |
6 | // const updaterFeedURL = 'https://api.github.com/repos/iagocavalcante/qtube/releases/latest'
7 |
8 | export const appUpdater = () => {
9 | const updaterFeedURL = `https://qtube-release.herokuapp.com/update/${platform}/${version}`
10 | autoUpdater.setFeedURL(updaterFeedURL);
11 | /* Log whats happening
12 | TODO send autoUpdater events to renderer so that we could console log it in developer tools
13 | You could alsoe use nslog or other logging to see what's happening */
14 | autoUpdater.on('error', err => console.log(err))
15 | autoUpdater.on('checking-for-update', () => console.log('checking-for-update'))
16 | autoUpdater.on('update-available', () => console.log('update-available'))
17 | autoUpdater.on('update-not-available', () => console.log('update-not-available'))
18 |
19 | // Ask the user if update is available
20 | autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
21 | let message = `${app.getName()} ${releaseName} is now available. It will be installed the next time you restart the application.`
22 | if (releaseNotes) {
23 | const splitNotes = releaseNotes.split(/[^\r]\n/)
24 | message += '\n\nRelease notes:\n'
25 | splitNotes.forEach(notes => {
26 | message += `${notes} \n\n`
27 | })
28 | }
29 | app.webContents.send('updateReady')
30 | // Ask user to update the app
31 | dialog.showMessageBox({
32 | type: 'question',
33 | buttons: ['Install and Relaunch', 'Later'],
34 | defaultId: 0,
35 | message: `A new version of ${app.getName()} has been downloaded`,
36 | detail: message
37 | }, response => {
38 | if (response === 0) {
39 | setTimeout(() => autoUpdater.quitAndInstall(), 1)
40 | }
41 | })
42 | })
43 | // init for updates
44 | autoUpdater.checkForUpdates()
45 | }
46 |
47 | export default {
48 | appUpdater
49 | }
--------------------------------------------------------------------------------
/src-electron/main-process/electron-main.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | // Install `electron-debug` with `devtron`
9 | require('electron-debug')({ showDevTools: true })
10 |
11 | // Install `vue-devtools`
12 | require('electron').app.on('ready', () => {
13 | let installExtension = require('electron-devtools-installer')
14 | installExtension.default(installExtension.VUEJS_DEVTOOLS)
15 | .then(() => {})
16 | .catch(err => {
17 | console.log('Unable to install `vue-devtools`: \n', err)
18 | })
19 | })
20 |
21 | // Require `main` process to boot app
22 | require('./electron-main')
23 |
--------------------------------------------------------------------------------
/src-electron/main-process/electron-main.js:
--------------------------------------------------------------------------------
1 | import { app, BrowserWindow, ipcMain } from 'electron'
2 | import server from './server/server.js'
3 | // import utilUpdater from './auto-updater/auto-updater.js'
4 | import { autoUpdater } from 'electron-updater'
5 | import fs from 'fs'
6 | const log = require('electron-log')
7 | /**
8 | * Set `__statics` path to static files in production
9 | * The reason we are setting it here is that the path needs to be evaluated at runtime
10 | */
11 | if (process.env.PROD) {
12 | global.__statics = require('path').join(__dirname, 'statics').replace(/\\/g, '\\\\')
13 | }
14 |
15 | // configure logging
16 | autoUpdater.logger = log
17 | autoUpdater.logger.transports.file.level = 'info'
18 | log.info('App starting...')
19 |
20 | const defaultPath = `${app.getPath('downloads')}/Ytdown/`.replace(/\\/g, '/')
21 |
22 | let mainWindow
23 |
24 | function createWindow () {
25 | /**
26 | * Initial window options
27 | */
28 | mainWindow = new BrowserWindow({
29 | width: 1000,
30 | height: 600,
31 | useContentSize: true,
32 | frame: process.env.PROD ? false : true,
33 | webPreferences: {
34 | webSecurity: false
35 | }
36 | })
37 |
38 |
39 | mainWindow.loadURL(process.env.APP_URL)
40 |
41 | mainWindow.on('closed', () => {
42 | mainWindow = null
43 | })
44 |
45 | server.listen(defaultPath)
46 | }
47 |
48 | // when receiving a quitAndInstall signal, quit and install the new version )
49 | ipcMain.on('quitAndInstall', (event, arg) => {
50 | autoUpdater.quitAndInstall()
51 | })
52 |
53 | ipcMain.on('close-app', (event) => {
54 | if (process.platform !== 'darwin') {
55 | app.quit()
56 | }
57 | })
58 |
59 | ipcMain.on('minimize', (event) => {
60 | mainWindow.minimize()
61 | })
62 |
63 | ipcMain.on('createYtDownFolder', function (event) {
64 |
65 | if (!fs.existsSync(defaultPath)) { //check if default folder already exists
66 | fs.mkdirSync(defaultPath, '0o765')
67 | event.returnValue = defaultPath
68 | } else {
69 | event.returnValue = defaultPath
70 | }
71 |
72 | })
73 |
74 | ipcMain.on('createVideosFolder', function (event) {
75 | const videosPath = `${defaultPath}/videos`.replace(/\\/g, '/')
76 | if (!fs.existsSync(videosPath)) { //check if default folder already exists
77 | fs.mkdirSync(videosPath, '0o765')
78 | event.returnValue = videosPath
79 | } else {
80 | event.returnValue = videosPath
81 | }
82 | })
83 |
84 | ipcMain.on('createDatabaseFolder', function (event) {
85 | const databasePath = `${defaultPath}/database`.replace(/\\/g, '/')
86 | if (!fs.existsSync(databasePath)) { //check if default folder already exists
87 | fs.mkdirSync(databasePath, '0o765')
88 | event.returnValue = databasePath
89 | } else {
90 | event.returnValue = databasePath
91 | }
92 | })
93 |
94 | ipcMain.on('createMusicFolder', function (event) {
95 | const musicsPath = `${defaultPath}/musics`.replace(/\\/g, '/')
96 | if (!fs.existsSync(musicsPath)) { //check if default folder already exists
97 | fs.mkdirSync(musicsPath, '0o765')
98 | event.returnValue = musicsPath
99 | } else {
100 | event.returnValue = musicsPath
101 | }
102 | })
103 |
104 | ipcMain.on('createFileDatabase', function (event) {
105 | const databasePath = `${defaultPath}/database`.replace(/\\/g, '/')
106 | if (!fs.existsSync(`${databasePath}/ytdown.json`)) {
107 | const yt = {
108 | videos: [],
109 | musics: [],
110 | }
111 | fs.writeFileSync(`${databasePath}/ytdown.json`, JSON.stringify(yt))
112 | event.returnValue = `${databasePath}/ytdown.json`
113 | } else {
114 | event.returnValue = `${databasePath}/ytdown.json`
115 | }
116 | })
117 |
118 | ipcMain.on('getFolderApp', (event) => {
119 | event.returnValue = defaultPath
120 | })
121 |
122 | app.on('ready', () => {
123 | autoUpdater.checkForUpdatesAndNotify()
124 | createWindow
125 | })
126 |
127 | app.on('window-all-closed', () => {
128 | if (process.platform !== 'darwin') {
129 | app.quit()
130 | }
131 | })
132 |
133 | app.on('activate', () => {
134 | if (mainWindow === null) {
135 | createWindow()
136 | }
137 | })
138 |
139 | function sendStatusToWindow(text) {
140 | const dialogOpts = {
141 | type: 'info',
142 | buttons: ['Ok'],
143 | title: 'Atualização do aplicativo',
144 | message: 'Detalhes:',
145 | detail: text
146 | }
147 |
148 | dialog.showMessageBox(dialogOpts)
149 | }
150 |
151 | autoUpdater.on('checking-for-update', () => {
152 | sendStatusToWindow('Checking for update...');
153 | })
154 |
155 | autoUpdater.on('update-available', (info) => {
156 | sendStatusToWindow('Update available.');
157 | })
158 |
159 | autoUpdater.on('update-not-available', (info) => {
160 | sendStatusToWindow('Update not available.');
161 | })
162 |
163 | autoUpdater.on('error', (err) => {
164 | sendStatusToWindow('Error in auto-updater. ' + err);
165 | })
166 |
167 | autoUpdater.on('download-progress', (progressObj) => {
168 | let log_message = "Download speed: " + progressObj.bytesPerSecond;
169 | log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
170 | log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
171 | sendStatusToWindow(log_message);
172 | })
173 |
174 | autoUpdater.on('update-downloaded', (info) => {
175 | sendStatusToWindow('Update downloaded');
176 | });
177 |
178 | app.on('ready', function () {
179 | autoUpdater.checkForUpdatesAndNotify();
180 | createWindow();
181 | });
182 |
--------------------------------------------------------------------------------
/src-electron/main-process/server/modules/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | manipulateFiles: require('./manipulate-files')
3 | }
--------------------------------------------------------------------------------
/src-electron/main-process/server/modules/manipulate-files/index.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 |
3 | const createDir = (directory) => {
4 | fs.mkdir(directory, function (err) {
5 | if (err) {
6 | console.log(err)
7 | }
8 | })
9 | }
10 |
11 | module.exports = {
12 | createDir
13 | }
14 |
--------------------------------------------------------------------------------
/src-electron/main-process/server/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const bodyParser = require('body-parser')
3 | const fs = require('fs')
4 | const path = require('path')
5 | const ytdl = require('ytdl-core')
6 | const { promisify } = require('util')
7 | const cors = require('cors')
8 | const getInfoVideo = promisify(ytdl.getInfo)
9 | const modules = require('./modules')
10 | const request = require('request')
11 | const ffmpeg = require('fluent-ffmpeg')
12 | export const listen = (__statics) => {
13 | const app = express()
14 |
15 | app.use(bodyParser.json({ limit: '250mb' }));
16 | app.use(bodyParser.urlencoded({ limit: '250mb', extended: true }));
17 | app.use(cors())
18 | app.use(express.static(path.join(__statics, 'videos')))
19 |
20 | app.post('/api/download', async (req, res) => {
21 | try {
22 | const info = await getInfoVideo(req.body.youtubeUrl.replace('https://www.youtube.com/watch?v=', ''))
23 | const title = info.title.replace(/[!?@#$%^&*|\.\;]/g, "")
24 | modules.manipulateFiles.createDir(path.join(__statics, `videos/${title}/`))
25 | ytdl(req.body.youtubeUrl)
26 | .pipe(fs.createWriteStream(path.join(__statics, `videos/${title}/${title}.mp4`)))
27 | .on('finish', () => {
28 | request.post('http://localhost:3000/api/thumbnail', { form: { info: info } })
29 | res.status(200).json({ video: `ok` })
30 | })
31 | } catch (err) {
32 | res.status(500).json(err)
33 | }
34 | })
35 |
36 | app.post('/api/download-mp3', async (req, res) => {
37 | try {
38 | const videoId = req.body.youtubeUrl.replace('https://www.youtube.com/watch?v=', '')
39 | const info = await getInfoVideo(videoId)
40 | const title = info.title.replace(/[!?@#$%^&*|\.\;]/g, "")
41 | modules.manipulateFiles.createDir(path.join(__statics, `musics/${title}/`))
42 | const stream = ytdl(videoId, {
43 | quality: 'highestaudio',
44 | filter: 'audioonly',
45 | })
46 | ffmpeg(stream)
47 | .audioBitrate(128)
48 | .save(path.join(__statics, `musics/${title}/${title}.mp3`))
49 | .on('progress', (p) => {
50 | console.log(`${p.targetSize}kb downloaded`);
51 | })
52 | .on('end', () => {
53 | request.post('http://localhost:3000/api/thumbnail', { form: { info: info, type: 'mp3' } })
54 | res.status(200).json({ musicLink: path.join(__statics, `musics/${title}/${title}.mp3`) })
55 | })
56 | } catch (err) {
57 | res.status(500).json(err)
58 | }
59 | })
60 |
61 | app.post('/api/download-playlist', async (req, res) => {
62 | try {
63 | const videoId = req.body.youtubeUrl
64 | const info = await getInfoVideo(videoId)
65 | const title = info.title.replace(/[!?@#$%^&*|\.\;]/g, "")
66 | modules.manipulateFiles.createDir(path.join(__statics, `musics/${title}/`))
67 | playlist(videoId, title)
68 | res.status(200).json({ musicLink: path.join(__statics, `musics/${title}/${title}.mp3`) })
69 | } catch (err) {
70 | res.status(500).json(err)
71 | }
72 | })
73 |
74 | const playlist = (videoId, title) => {
75 | const stream = ytdl(videoId, {
76 | quality: 'highestaudio',
77 | filter: 'audioonly',
78 | })
79 |
80 | stream.on('error', function error(err) {
81 | console.log(err.stack);
82 | });
83 |
84 | var size = 0;
85 | stream.on('info', function (info) {
86 | size = info.size;
87 | var output = path.join(__statics, `musics/${title}/${title}.mp3`);
88 | stream.pipe(fs.createWriteStream(output));
89 | });
90 |
91 | var pos = 0;
92 | stream.on('data', function data(chunk) {
93 | pos += chunk.length;
94 | // `size` should not be 0 here.
95 | if (size) {
96 | var percent = (pos / size * 100).toFixed(2);
97 | process.stdout.cursorTo(0);
98 | process.stdout.clearLine(1);
99 | process.stdout.write(percent + '%');
100 | }
101 | });
102 |
103 | stream.on('next', playlist);
104 | }
105 |
106 | app.get('/api/infos', (req, res) => {
107 | fs.readFile(path.join(__statics, 'database/ytdown.json'), function (err, content) {
108 | if (err) console.log(err)
109 | // if (err) res.status(500).json({ error: 'impossible insert data' })
110 | const yt = JSON.parse(content)
111 | res.status(200).json(yt)
112 | })
113 | })
114 |
115 | app.post('/api/thumbnail', (req, res) => {
116 | const info = req.body.info
117 | const type = req.body.type
118 | const title = info.title.replace(/[!?@#$%^&*|\.\;]/g, "")
119 | const filePath = type === 'mp3' ? path.join(__statics, `musics/${title}/${title}.jpg`) : path.join(__statics, `videos/${title}/${title}.jpg`)
120 | request.get(info.thumbnail_url).pipe(fs.createWriteStream(filePath))
121 | .on('finish', () => {
122 | request.post('http://localhost:3000/api/insert', { form: { info: info, type: type } })
123 | res.status(200).json({ img: `ok` })
124 | })
125 | })
126 |
127 | app.post('/api/insert', (req, res) => {
128 | const info = req.body.info
129 | const type = req.body.type
130 | const title = info.title.replace(/[!?@#$%^&*|\.\;]/g, "")
131 | const ytdown = {
132 | title: title,
133 | description: info.description,
134 | thumbnail: type === 'mp3' ? `musics/${title}/${title}.jpg` : `videos/${title}/${title}.jpg`,
135 | src: type === 'mp3' ? `musics/${title}/${title}.mp3` : `videos/${title}/${title}.mp4`
136 | }
137 | let yt = {}
138 | fs.readFile(path.join(__statics, 'database/ytdown.json'), function (err, content) {
139 | if (err) console.log(err)
140 | // if (err) res.status(500).json({ error: 'impossible insert data' })
141 | yt = JSON.parse(content)
142 | if (type === 'mp3')
143 | yt.musics.push(ytdown)
144 | else
145 | yt.videos.push(ytdown)
146 | fs.writeFile(path.join(__statics, 'database/ytdown.json'), JSON.stringify(yt), function (err) {
147 | // if (err) res.status(500).json({ error: 'impossible insert data' })
148 | if (err) console.log(err)
149 | })
150 | })
151 | res.status(200).json({ img: `ok` })
152 | })
153 |
154 | app.listen(3000)
155 | }
156 |
157 | export default {
158 | listen
159 | }
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
15 |
--------------------------------------------------------------------------------
/src/assets/logo-qtube-horizontal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/logo-qtube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/quasar-logo-full.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
192 |
--------------------------------------------------------------------------------
/src/assets/sad.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/components/.gitkeep
--------------------------------------------------------------------------------
/src/components/videoPlayer.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
14 |
15 |
65 |
66 |
68 |
--------------------------------------------------------------------------------
/src/css/app.styl:
--------------------------------------------------------------------------------
1 | // app global css
2 |
--------------------------------------------------------------------------------
/src/css/themes/common.variables.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // To customize the look and feel of this app, you can override
4 | // the Stylus variables found in Quasar's source Stylus files. Setting
5 | // variables before Quasar's Stylus will use these variables rather than
6 | // Quasar's default Stylus variable values. Stylus variables specific
7 | // to the themes belong in either the variables.ios.styl or variables.mat.styl files.
8 |
9 | // Check documentation for full list of Quasar variables
10 |
11 |
12 | // App Shared Color Variables
13 | // --------------------------------------------------
14 | // It's highly recommended to change the default colors
15 | // to match your app's branding.
16 |
17 | $primary = #027be3
18 | $secondary = #26A69A
19 | $tertiary = #555
20 |
21 | $neutral = #E0E1E2
22 | $positive = #21BA45
23 | $negative = #DB2828
24 | $info = #31CCEC
25 | $warning = #F2C037
26 |
--------------------------------------------------------------------------------
/src/css/themes/variables.ios.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // Shared Stylus variables go in the common.variables.styl file
4 | @import 'common.variables'
5 |
6 | // iOS only Quasar variables overwrites
7 | // -----------------------------------------
8 |
--------------------------------------------------------------------------------
/src/css/themes/variables.mat.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // Shared Stylus variables go in the common.variables.styl file
4 | @import 'common.variables'
5 |
6 | // Material only Quasar variables overwrites
7 | // -----------------------------------------
8 |
--------------------------------------------------------------------------------
/src/i18n/en-us/index.js:
--------------------------------------------------------------------------------
1 | // This is just an example,
2 | // so you can safely delete all default props below
3 |
4 | export default {
5 | failed: 'Action failed',
6 | success: 'Action was successful'
7 | }
8 |
--------------------------------------------------------------------------------
/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import enUS from './en-us'
2 |
3 | export default {
4 | 'en-us': enUS
5 | }
6 |
--------------------------------------------------------------------------------
/src/index.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | <%= htmlWebpackPlugin.options.productName %>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
79 |
80 |
101 |
--------------------------------------------------------------------------------
/src/pages/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
Sorry, nothing here...(404)
10 |
Go back
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{option.type}}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
111 |
--------------------------------------------------------------------------------
/src/pages/musics.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{info.title}}
14 | {{info.title}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | PLAY
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Don't find any musics in your app!!
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
82 |
83 |
85 |
--------------------------------------------------------------------------------
/src/pages/player.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
32 |
33 |
35 |
--------------------------------------------------------------------------------
/src/pages/videos.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{info.title}}
14 | {{info.title}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | VIEW
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Don't find any videos in your app!!
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
82 |
83 |
85 |
--------------------------------------------------------------------------------
/src/plugins/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/plugins/.gitkeep
--------------------------------------------------------------------------------
/src/plugins/axios.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export default ({ Vue }) => {
4 | Vue.prototype.$axios = axios
5 | }
6 |
--------------------------------------------------------------------------------
/src/plugins/i18n.js:
--------------------------------------------------------------------------------
1 | import VueI18n from 'vue-i18n'
2 | import messages from 'src/i18n'
3 |
4 | export default ({ app, Vue }) => {
5 | Vue.use(VueI18n)
6 |
7 | // Set i18n instance on app
8 | app.i18n = new VueI18n({
9 | locale: 'en-us',
10 | fallbackLocale: 'en-us',
11 | messages
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/src/plugins/video-player.js:
--------------------------------------------------------------------------------
1 | import VueVideoPlayer from 'vue-video-player'
2 | // leave the export, even if you don't use it
3 | export default ({ Vue }) => {
4 | // something to do
5 | Vue.use(VueVideoPlayer)
6 | }
7 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 |
4 | import routes from './routes'
5 |
6 | Vue.use(VueRouter)
7 |
8 | const Router = new VueRouter({
9 | /*
10 | * NOTE! Change Vue Router mode from quasar.conf.js -> build -> vueRouterMode
11 | *
12 | * When going with "history" mode, please also make sure "build.publicPath"
13 | * is set to something other than an empty string.
14 | * Example: '/' instead of ''
15 | */
16 |
17 | // Leave as is and change from quasar.conf.js instead!
18 | mode: process.env.VUE_ROUTER_MODE,
19 | base: process.env.VUE_ROUTER_BASE,
20 | scrollBehavior: () => ({ y: 0 }),
21 | routes
22 | })
23 |
24 | export default Router
25 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 |
2 | export default [
3 | {
4 | path: '/',
5 | redirect: '/index',
6 | component: () => import('layouts/default'),
7 | children: [
8 | { path: 'index', component: () => import('pages/index') },
9 | { path: 'videos', component: () => import('pages/videos') },
10 | { path: 'musics', component: () => import('pages/musics') },
11 | { path: 'player/:src/:img', name: 'player', component: () => import('pages/player') }
12 | ]
13 | },
14 | { // Always leave this as last one
15 | path: '*',
16 | component: () => import('pages/404')
17 | }
18 | ]
19 |
--------------------------------------------------------------------------------
/src/statics/darkrola.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/darkrola.jpeg
--------------------------------------------------------------------------------
/src/statics/icons/apple-icon-152x152-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/apple-icon-152x152-.png
--------------------------------------------------------------------------------
/src/statics/icons/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/apple-icon-152x152.png
--------------------------------------------------------------------------------
/src/statics/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/src/statics/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-128x128-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-128x128-.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-128x128.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-192x192-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-192x192-.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-192x192.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-256x256.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-256x256asd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-256x256asd.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-256x256beta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-256x256beta.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-384x384-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-384x384-.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-384x384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-384x384.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-512x512-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-512x512-.png
--------------------------------------------------------------------------------
/src/statics/icons/icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/icon-512x512.png
--------------------------------------------------------------------------------
/src/statics/icons/ms-icon-144x144-.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/ms-icon-144x144-.png
--------------------------------------------------------------------------------
/src/statics/icons/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/icons/ms-icon-144x144.png
--------------------------------------------------------------------------------
/src/statics/quasar-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iagocavalcante/qtube/91cd3dc960adcbde12a4601fdc3de67be0fbd0f0/src/statics/quasar-logo.png
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | import example from './module-example'
5 |
6 | Vue.use(Vuex)
7 |
8 | const store = new Vuex.Store({
9 | modules: {
10 | example
11 | }
12 | })
13 |
14 | export default store
15 |
--------------------------------------------------------------------------------
/src/store/module-example/actions.js:
--------------------------------------------------------------------------------
1 | /*
2 | export const someAction = (state) => {
3 | }
4 | */
5 |
--------------------------------------------------------------------------------
/src/store/module-example/getters.js:
--------------------------------------------------------------------------------
1 | /*
2 | export const someGetter = (state) => {
3 | }
4 | */
5 |
--------------------------------------------------------------------------------
/src/store/module-example/index.js:
--------------------------------------------------------------------------------
1 | import state from './state'
2 | import * as getters from './getters'
3 | import * as mutations from './mutations'
4 | import * as actions from './actions'
5 |
6 | export default {
7 | namespaced: true,
8 | state,
9 | getters,
10 | mutations,
11 | actions
12 | }
13 |
--------------------------------------------------------------------------------
/src/store/module-example/mutations.js:
--------------------------------------------------------------------------------
1 | /*
2 | export const someMutation = (state) => {
3 | }
4 | */
5 |
--------------------------------------------------------------------------------
/src/store/module-example/state.js:
--------------------------------------------------------------------------------
1 | export default {
2 | //
3 | }
4 |
--------------------------------------------------------------------------------