Merge pull request #1 from FreeTubeApp/master

Catch up to upstream
This commit is contained in:
Hiers 2020-08-29 17:06:30 +00:00 committed by GitHub
commit 0696b9fd4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 697 additions and 335 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
.DS_Store
dist/electron/*
storyboards/*
dashFiles/*
dist/web/*
build/*
!build/icons

574
package-lock.json generated
View File

@ -2258,6 +2258,58 @@
}
}
},
"@malept/cross-spawn-promise": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.0.tgz",
"integrity": "sha512-GeIK5rfU1Yd7BZJQPTGZMMmcZy5nhRToPXZcjaDwQDRSewdhp648GT2E4dh+L7+Io7AOW6WQ+GR44QSzja4qxg==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.1"
},
"dependencies": {
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"@nodelib/fs.scandir": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
@ -2607,12 +2659,12 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.9.1.tgz",
"integrity": "sha512-XIr+Mfv7i4paEdBf0JFdIl9/tVxyj+rlilWIfZ97Be0lZ7hPvUbS5iHt9Glc8kRI53dsr0PcAEudbf8rO2wGgg==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz",
"integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "3.9.1",
"@typescript-eslint/experimental-utils": "3.10.1",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
@ -2644,45 +2696,45 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.9.1.tgz",
"integrity": "sha512-lkiZ8iBBaYoyEKhCkkw4SAeatXyBq9Ece5bZXdLe1LWBUwTszGbmbiqmQbwWA8cSYDnjWXp9eDbXpf9Sn0hLAg==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz",
"integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/types": "3.9.1",
"@typescript-eslint/typescript-estree": "3.9.1",
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/typescript-estree": "3.10.1",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.9.1.tgz",
"integrity": "sha512-y5QvPFUn4Vl4qM40lI+pNWhTcOWtpZAJ8pOEQ21fTTW4xTJkRplMjMRje7LYTXqVKKX9GJhcyweMz2+W1J5bMg==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz",
"integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "3.9.1",
"@typescript-eslint/types": "3.9.1",
"@typescript-eslint/typescript-estree": "3.9.1",
"@typescript-eslint/experimental-utils": "3.10.1",
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/typescript-estree": "3.10.1",
"eslint-visitor-keys": "^1.1.0"
}
},
"@typescript-eslint/types": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.9.1.tgz",
"integrity": "sha512-15JcTlNQE1BsYy5NBhctnEhEoctjXOjOK+Q+rk8ugC+WXU9rAcS2BYhoh6X4rOaXJEpIYDl+p7ix+A5U0BqPTw==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz",
"integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.9.1.tgz",
"integrity": "sha512-IqM0gfGxOmIKPhiHW/iyAEXwSVqMmR2wJ9uXHNdFpqVvPaQ3dWg302vW127sBpAiqM9SfHhyS40NKLsoMpN2KA==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz",
"integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==",
"dev": true,
"requires": {
"@typescript-eslint/types": "3.9.1",
"@typescript-eslint/visitor-keys": "3.9.1",
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/visitor-keys": "3.10.1",
"debug": "^4.1.1",
"glob": "^7.1.6",
"is-glob": "^4.0.1",
@ -2738,9 +2790,9 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.9.1.tgz",
"integrity": "sha512-zxdtUjeoSh+prCpogswMwVUJfEFmCOjdzK9rpNjNBfm6EyPt99x3RrJoBOGZO23FCt0WPKUCOL5mb/9D5LjdwQ==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz",
"integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
@ -5245,12 +5297,12 @@
"dev": true
},
"cli-cursor": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dev": true,
"requires": {
"restore-cursor": "^2.0.0"
"restore-cursor": "^3.1.0"
}
},
"cli-spinners": {
@ -6059,16 +6111,15 @@
"dev": true
},
"css-loader": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.2.1.tgz",
"integrity": "sha512-MoqmF1if7Z0pZIEXA4ZF9PgtCXxWbfzfJM+3p+OYfhcrwcqhaCRb74DSnfzRl7e024xEiCRn5hCvfUbTf2sgFA==",
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.2.2.tgz",
"integrity": "sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg==",
"dev": true,
"requires": {
"camelcase": "^6.0.0",
"cssesc": "^3.0.0",
"icss-utils": "^4.1.1",
"loader-utils": "^2.0.0",
"normalize-path": "^3.0.0",
"postcss": "^7.0.32",
"postcss-modules-extract-imports": "^2.0.0",
"postcss-modules-local-by-default": "^3.0.3",
@ -6080,9 +6131,9 @@
},
"dependencies": {
"ajv": {
"version": "6.12.3",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
"version": "6.12.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@ -6154,12 +6205,6 @@
"json5": "^2.1.2"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"postcss": {
"version": "7.0.32",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz",
@ -6858,9 +6903,9 @@
}
},
"electron": {
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-9.2.1.tgz",
"integrity": "sha512-ZsetaQjXB8+9/EFW1FnfK4ukpkwXCxMEaiKiUZhZ0ZLFlLnFCpe0Bg4vdDf7e4boWGcnlgN1jAJpBw7w0eXuqA==",
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-10.1.0.tgz",
"integrity": "sha512-DyS6WhQ59+ZXQsI1EkpsYkOXFt0Xbp+mbxPTJS9A7O21r3JDzaTC+1Jxz7g6J+Sbi9Y7UFdRs0tn/vqhHJx2gA==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@ -7383,33 +7428,22 @@
}
},
"electron-rebuild": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-2.0.0.tgz",
"integrity": "sha512-A+acX+oU2g1ImoEuQGfsYWOGKCq757KyMN/INSVMiNvjqzE6tmZ4/xim6Q1Rca9aRhep+QdMVwoIVsp/jq0woQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-2.0.1.tgz",
"integrity": "sha512-oXCnKKS+FpLxXiiSHtSCFI3zo+4H2y6zUegSQTI031RJXn2fzQV9UJMAfBrnW7Z083chIo3/L4+xFM4R8mreOQ==",
"dev": true,
"requires": {
"@malept/cross-spawn-promise": "^1.1.0",
"colors": "^1.3.3",
"debug": "^4.1.1",
"detect-libc": "^1.0.3",
"fs-extra": "^8.1.0",
"node-abi": "^2.11.0",
"fs-extra": "^9.0.1",
"node-abi": "^2.19.1",
"node-gyp": "^7.1.0",
"ora": "^3.4.0",
"spawn-rx": "^3.0.0",
"yargs": "^14.2.0"
"ora": "^5.0.0",
"yargs": "^15.4.1"
},
"dependencies": {
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@ -7419,61 +7453,97 @@
"ms": "^2.1.1"
}
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"fs-extra": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
"dev": true,
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
"p-limit": "^2.2.0"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
"dev": true
},
"yargs": {
"version": "14.2.3",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
"integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^3.0.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^15.0.1"
}
},
"yargs-parser": {
"version": "15.0.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
"integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
"yargs-parser": "^18.1.2"
}
}
}
@ -10730,6 +10800,12 @@
"is-path-inside": "^3.0.1"
}
},
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
"dev": true
},
"is-npm": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
@ -12986,9 +13062,9 @@
"dev": true
},
"klona": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/klona/-/klona-1.1.2.tgz",
"integrity": "sha512-xf88rTeHiXk+XE2Vhi6yj8Wm3gMZrygGdKjJqN8HkV+PwF/t50/LdAKHoHpPcxFAlmQszTZ1CugrK25S7qDRLA==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.3.tgz",
"integrity": "sha512-CgPOT3ZadDpXxKcfV56lEQ9OQSZ42Mk26gnozI+uN/k39vzD8toUhRQoqsX0m9Q3eMPEfsLWmtyUpK/yqST4yg==",
"dev": true
},
"latest-version": {
@ -13115,12 +13191,6 @@
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
"dev": true
},
"lodash.assignin": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
@ -13216,12 +13286,64 @@
"dev": true
},
"log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dev": true,
"requires": {
"chalk": "^2.0.1"
"chalk": "^4.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"loglevel": {
@ -13527,9 +13649,9 @@
}
},
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
"mimic-response": {
@ -13547,9 +13669,9 @@
}
},
"mini-css-extract-plugin": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.0.tgz",
"integrity": "sha512-QgKgJBjaJhxVPwrLNqqwNS0AGkuQQ31Hp4xGXEK/P7wehEg6qmNtReHKai3zRXqY60wGVWLYcOMJK2b98aGc3A==",
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.0.tgz",
"integrity": "sha512-dVWGuWJlQw2lZxsxBI3hOsoxg1k3DruLR0foHQLSkQMfk+qLJbv9dUk8fjmjWQKN9ef2n54ehA2FjClAsQhrWQ==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0",
@ -13772,6 +13894,12 @@
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
"dev": true
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
"mux.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.2.1.tgz",
@ -13857,9 +13985,9 @@
}
},
"node-abi": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.0.tgz",
"integrity": "sha512-rpKqVe24p9GvMTgtqUXdLR1WQJBGVlkYPU10qHKv9/1i9V/k04MmFLVK2WcHBf1WKKY+ZsdvARPi8F4tfJ4opA==",
"version": "2.19.1",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz",
"integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==",
"dev": true,
"requires": {
"semver": "^5.4.1"
@ -14612,12 +14740,12 @@
}
},
"onetime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
"requires": {
"mimic-fn": "^1.0.0"
"mimic-fn": "^2.1.0"
}
},
"opml-to-json": {
@ -14689,28 +14817,84 @@
}
},
"ora": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
"integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.0.0.tgz",
"integrity": "sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"cli-cursor": "^2.1.0",
"cli-spinners": "^2.0.0",
"log-symbols": "^2.2.0",
"strip-ansi": "^5.2.0",
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.4.0",
"is-interactive": "^1.0.0",
"log-symbols": "^4.0.0",
"mute-stream": "0.0.8",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"dev": true
},
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.0"
}
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
@ -15327,9 +15511,9 @@
"dev": true
},
"prettier": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
"integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
"integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
"dev": true
},
"prettier-linter-helpers": {
@ -16231,12 +16415,12 @@
}
},
"restore-cursor": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dev": true,
"requires": {
"onetime": "^2.0.0",
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
@ -16330,15 +16514,6 @@
"individual": "^2.0.0"
}
},
"rxjs": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -16402,12 +16577,12 @@
}
},
"sass-loader": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-9.0.3.tgz",
"integrity": "sha512-fOwsP98ac1VMme+V3+o0HaaMHp8Q/C9P+MUazLFVi3Jl7ORGHQXL1XeRZt3zLSGZQQPC8xE42Y2WptItvGjDQg==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.1.tgz",
"integrity": "sha512-b2PSldKVTS3JcFPHSrEXh3BeAfR7XknGiGCAO5aHruR3Pf3kqLP3Gb2ypXLglRrAzgZkloNxLZ7GXEGDX0hBUQ==",
"dev": true,
"requires": {
"klona": "^1.1.2",
"klona": "^2.0.3",
"loader-utils": "^2.0.0",
"neo-async": "^2.6.2",
"schema-utils": "^2.7.0",
@ -16415,9 +16590,9 @@
},
"dependencies": {
"ajv": {
"version": "6.12.3",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
"version": "6.12.4",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@ -17005,17 +17180,6 @@
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
"dev": true
},
"spawn-rx": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-3.0.0.tgz",
"integrity": "sha512-dw4Ryg/KMNfkKa5ezAR5aZe9wNwPdKlnHEXtHOjVnyEDSPQyOpIPPRtcIiu7127SmtHhaCjw21yC43HliW0iIg==",
"dev": true,
"requires": {
"debug": "^2.5.1",
"lodash.assign": "^4.2.0",
"rxjs": "^6.3.1"
}
},
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@ -18872,6 +19036,11 @@
"vue-style-loader": "^4.1.0"
}
},
"vue-observe-visibility": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz",
"integrity": "sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q=="
},
"vue-router": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz",
@ -19926,6 +20095,14 @@
"xtend": "^4.0.0"
}
},
"xml-js": {
"version": "1.6.11",
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
"integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
"requires": {
"sax": "^1.2.4"
}
},
"xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
@ -20095,44 +20272,21 @@
}
},
"yt-channel-info": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/yt-channel-info/-/yt-channel-info-1.0.3.tgz",
"integrity": "sha512-AFFh403fCX+vRei+bExIwgO7OPDydbLdq57HtZIQ1bn7/f4w7Vv7Vh/G+HT9s5yIApbqrbR9uPetPWofG0KDuw==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/yt-channel-info/-/yt-channel-info-1.1.0.tgz",
"integrity": "sha512-BFcJvzBoLN9k7gABt11PILwk1ywgY97606He8YoCk+RP315n8uMdpPFOKx+KP/sTQV+A48oMvGvjiMU9HDnNtA==",
"requires": {
"axios": "^0.18.0",
"axios": "^0.19.2",
"querystring": "^0.2.0"
},
"dependencies": {
"axios": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
"integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
}
},
"is-buffer": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
}
}
},
"yt-dash-manifest-generator": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/yt-dash-manifest-generator/-/yt-dash-manifest-generator-1.0.2.tgz",
"integrity": "sha512-rcBsAAhwlxtW/9irXRbU8N/8Qpft96OO0pLFvF8O7nDrjRWljnJC+DheXuhYGXpMqJGksROH1xQ1bHpwwp310g==",
"requires": {
"xml-js": "^1.6.11",
"ytdl-core": "^3.2.2"
}
},
"yt-trending-scraper": {

View File

@ -33,6 +33,7 @@
"vue": "^2.6.12",
"vue-electron": "^1.0.6",
"vue-i18n": "^8.21.0",
"vue-observe-visibility": "^0.4.6",
"vue-router": "^3.4.3",
"vuex": "^3.5.1",
"xml2json": "^0.12.0",
@ -40,7 +41,8 @@
"youtube-comments-fetch": "^1.0.1",
"youtube-comments-task": "^1.3.15",
"youtube-suggest": "^1.1.0",
"yt-channel-info": "^1.0.3",
"yt-channel-info": "^1.1.0",
"yt-dash-manifest-generator": "^1.0.2",
"yt-trending-scraper": "^1.0.3",
"yt-xml2vtt": "^1.1.2",
"ytdl-core": "^3.2.2",
@ -54,19 +56,19 @@
"@babel/plugin-proposal-object-rest-spread": "^7.11.0",
"@babel/preset-env": "^7.11.0",
"@babel/preset-typescript": "^7.10.4",
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.9.1",
"@typescript-eslint/eslint-plugin": "^3.10.1",
"@typescript-eslint/parser": "^3.10.1",
"acorn": "^8.0.1",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"copy-webpack-plugin": "^6.0.3",
"css-loader": "^4.2.1",
"css-loader": "^4.2.2",
"devtron": "^1.4.0",
"electron": "^9.2.1",
"electron": "^10.0.1",
"electron-builder": "^22.8.0",
"electron-builder-squirrel-windows": "^22.8.1",
"electron-debug": "^3.1.0",
"electron-rebuild": "^2.0.0",
"electron-rebuild": "^2.0.1",
"eslint": "^7.7.0",
"eslint-config-prettier": "^6.11.0",
"eslint-config-standard": "^14.1.1",
@ -80,13 +82,13 @@
"file-loader": "^6.0.0",
"html-webpack-plugin": "^4.3.0",
"jest": "^26.4.2",
"mini-css-extract-plugin": "^0.10.0",
"node-abi": "^2.19.0",
"mini-css-extract-plugin": "^0.11.0",
"node-abi": "^2.19.1",
"node-loader": "^1.0.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"prettier": "^2.1.1",
"sass": "^1.26.10",
"sass-loader": "^9.0.3",
"sass-loader": "^10.0.1",
"style-loader": "^1.2.1",
"tree-kill": "1.2.2",
"typescript": "^4.0.2",

View File

@ -74,7 +74,8 @@ function createWindow () {
nodeIntegration: true,
nodeIntegrationInWorker: false,
webSecurity: false,
backgroundThrottling: false
backgroundThrottling: false,
enableRemoteModule: true
},
show: false
})

View File

@ -1,4 +1,5 @@
import Vue from 'vue'
import { ObserveVisibility } from 'vue-observe-visibility'
import TopNav from './components/top-nav/top-nav.vue'
import SideNav from './components/side-nav/side-nav.vue'
import FtToast from './components/ft-toast/ft-toast.vue'
@ -7,6 +8,8 @@ import $ from 'jquery'
let useElectron
let shell
Vue.directive('observe-visibility', ObserveVisibility)
if (window && window.process && window.process.type === 'renderer') {
/* eslint-disable-next-line */
shell = require('electron').shell

View File

@ -1,18 +1,14 @@
import Vue from 'vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import FtAutoGrid from '../ft-auto-grid/ft-auto-grid.vue'
import FtListVideo from '../ft-list-video/ft-list-video.vue'
import FtListChannel from '../ft-list-channel/ft-list-channel.vue'
import FtListPlaylist from '../ft-list-playlist/ft-list-playlist.vue'
import FtListLazyWrapper from '../ft-list-lazy-wrapper/ft-list-lazy-wrapper.vue'
export default Vue.extend({
name: 'FtElementList',
components: {
'ft-flex-box': FtFlexBox,
'ft-auto-grid': FtAutoGrid,
'ft-list-video': FtListVideo,
'ft-list-channel': FtListChannel,
'ft-list-playlist': FtListPlaylist
'ft-list-lazy-wrapper': FtListLazyWrapper
},
props: {
data: {

View File

@ -2,28 +2,14 @@
<ft-auto-grid
:grid="listType !== 'list'"
>
<template
<ft-list-lazy-wrapper
v-for="(result, index) in data"
>
<ft-list-channel
v-if="result.type === 'channel'"
:key="index"
appearance="result"
:data="result"
/>
<ft-list-video
v-if="result.type === 'video' || result.type === 'shortVideo'"
:key="index"
appearance="result"
:data="result"
/>
<ft-list-playlist
v-if="result.type === 'playlist'"
:key="index"
appearance="result"
:data="result"
/>
</template>
:key="index"
appearance="result"
:data="result"
:first-screen="index < 16"
:layout="listType"
/>
</ft-auto-grid>
</template>

View File

@ -0,0 +1,7 @@
.grid {
min-height: 264px;
}
.list {
min-height: 131px;
}

View File

@ -0,0 +1,41 @@
import Vue from 'vue'
import FtListVideo from '../ft-list-video/ft-list-video.vue'
import FtListChannel from '../ft-list-channel/ft-list-channel.vue'
import FtListPlaylist from '../ft-list-playlist/ft-list-playlist.vue'
export default Vue.extend({
name: 'FtListLazyWrapper',
components: {
'ft-list-video': FtListVideo,
'ft-list-channel': FtListChannel,
'ft-list-playlist': FtListPlaylist
},
props: {
data: {
type: Object,
required: true
},
appearance: {
type: String,
required: true
},
firstScreen: {
type: Boolean,
required: true
},
layout: {
type: String,
default: 'grid'
}
},
data: function () {
return {
visible: this.firstScreen
}
},
methods: {
onVisibilityChanged: function (visible) {
this.visible = visible
}
}
})

View File

@ -0,0 +1,31 @@
<template>
<div
v-observe-visibility="firstScreen ? false : {
callback: onVisibilityChanged,
once: true,
}"
:class="{
grid: layout === 'grid',
list: layout === 'list'
}"
>
<ft-list-channel
v-if="data.type === 'channel' && visible"
:appearance="appearance"
:data="data"
/>
<ft-list-video
v-if="(data.type === 'video' || data.type === 'shortVideo') && visible"
:appearance="appearance"
:data="data"
/>
<ft-list-playlist
v-if="data.type === 'playlist' && visible"
:appearance="appearance"
:data="data"
/>
</div>
</template>
<script src="./ft-list-lazy-wrapper.js" />
<style scoped src="./ft-list-lazy-wrapper.css" />

View File

@ -202,6 +202,9 @@ export default Vue.extend({
// For Invidious data, as duration is sent in seconds
calculateVideoDuration: function (lengthSeconds) {
if (typeof lengthSeconds === 'string') {
return lengthSeconds
}
let durationText = ''
let time = lengthSeconds
let hours = 0

View File

@ -5,7 +5,9 @@
>
<ft-card class="promptCard">
<slot>
<h2 class="center">{{ label }}</h2>
<h2 class="center">
{{ label }}
</h2>
<ft-flex-box>
<ft-button
v-for="(option, index) in optionNames"

View File

@ -193,6 +193,11 @@ export default Vue.extend({
watch: {
sourceList: function () {
this.determineFormatType()
},
captionList: function () {
this.player.caption({
data: this.captionList
})
}
},
mounted: function () {

View File

@ -78,6 +78,9 @@ export default Vue.extend({
const searchContainer = $('.searchContainer').get(0)
searchContainer.blur()
searchContainer.style.display = 'none'
} else {
const searchInput = $('.searchInput input').get(0)
searchInput.blur()
}
this.$store.dispatch('getVideoIdFromUrl', query).then((result) => {

View File

@ -100,7 +100,7 @@ export default Vue.extend({
},
subscribedText: function () {
return `${this.$t('Subscribe').toUpperCase()} ${this.subscriptionCountText}`
return `${this.$t('Channel.Subscribe').toUpperCase()} ${this.subscriptionCountText}`
},
dateString() {

View File

@ -270,7 +270,21 @@ export default Vue.extend({
this.channelThumbnail = result.author.avatar
this.channelId = result.author.id
this.playlistItems = result.items
this.playlistItems = result.items.map((video) => {
if (video.author.name !== null) {
const channelName = video.author.name
const channelId = video.author.ref.replace(/https:\/\/(www\.)?youtube\.com\/(user|channel)\//g, '')
video.author = channelName
video.authorId = channelId
} else {
video.author = ''
video.authorId = ''
}
video.videoId = video.id
video.lengthSeconds = video.duration
return video
})
this.isLoading = false
}).catch((err) => {
console.log(err)

View File

@ -23,24 +23,18 @@ Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.use(VueI18n)
// List of locales approved for use
const activeLocales = ['en-US', 'de-DE', 'fi', 'fr-FR', 'pt-BR', 'pt-PT', 'ru', 'vi', 'zh-CN', 'zh-TW']
const activeLocales = ['en-US', 'de-DE', 'es-MX', 'fi', 'fr-FR', 'ja', 'pt-BR', 'pt-PT', 'ru', 'vi', 'zh-CN', 'zh-TW']
const messages = {}
const fileLocation = isDev ? 'static/locales/' : `${__dirname}/static/locales/`
// Take active locales and load respective YAML file
activeLocales.forEach((locale) => {
try {
// File location when running in dev
const doc = yaml.safeLoad(fs.readFileSync(`static/locales/${locale}.yaml`))
const doc = yaml.safeLoad(fs.readFileSync(`${fileLocation}${locale}.yaml`))
messages[locale] = doc
} catch (e) {
console.log(e)
try {
// File location when compiled
const doc = yaml.safeLoad(fs.readFileSync(`${__dirname}/static/locales/${locale}.yaml`))
messages[locale] = doc
} catch (e) {
console.log(e)
}
}
})

View File

@ -3,6 +3,8 @@ import FtToastEvents from '../../components/ft-toast/ft-toast-events'
const state = {
isSideNavOpen: false,
sessionSearchHistory: [],
popularCache: null,
trendingCache: null,
searchSettings: {
sortBy: 'relevance',
time: '',
@ -42,6 +44,14 @@ const getters = {
return state.sessionSearchHistory
},
getPopularCache () {
return state.popularCache
},
getTrendingCache () {
return state.trendingCache
},
getSearchSettings () {
return state.searchSettings
}
@ -261,6 +271,14 @@ const mutations = {
}
},
setPopularCache (state, value) {
state.popularCache = value
},
setTrendingCache (state, value) {
state.trendingCache = value
},
setSearchSortBy (state, value) {
state.searchSettings.sortBy = value
},

View File

@ -132,12 +132,10 @@ const actions = {
ytGetVideoInformation ({}, videoId) {
return new Promise((resolve, reject) => {
console.log('Getting video info please wait...')
ytdl.getInfo(videoId).then((result, err) => {
if (err) {
reject(err)
} else {
resolve(result)
}
ytdl.getInfo(videoId).then((result) => {
resolve(result)
}).catch((err) => {
reject(err)
})
})
}

View File

@ -40,7 +40,7 @@
</span>
</div>
<ft-button
label="SUBSCRIBE"
:label="$t('Channel.Subscribe')"
background-color="var(--primary-color)"
text-color="var(--text-with-main-color)"
class="subscribeButton"
@ -78,7 +78,7 @@
:value="videoSelectValues[0]"
:select-names="videoSelectNames"
:select-values="videoSelectValues"
placeholder="Sort By"
:placeholder="$t('Search Filters.Sort By.Sort By')"
@change="videoSortBy = $event"
/>
<ft-select
@ -87,7 +87,7 @@
:value="playlistSelectValues[0]"
:select-names="playlistSelectNames"
:select-values="playlistSelectValues"
placeholder="Sort By"
:placeholder="$t('Search Filters.Sort By.Sort By')"
@change="playlistSortBy = $event"
/>
</ft-flex-box>

View File

@ -92,7 +92,20 @@ export default Vue.extend({
infoSource: 'local'
}
this.playlistItems = result.items
this.playlistItems = result.items.map((video) => {
if (video.author.name !== null) {
const channelName = video.author.name
const channelId = video.author.ref.replace(/https:\/\/(www\.)?youtube\.com\/(user|channel)\//g, '')
video.author = channelName
video.authorId = channelId
} else {
video.author = ''
video.authorId = ''
}
video.videoId = video.id
video.lengthSeconds = video.duration
return video
})
this.isLoading = false
}).catch((err) => {

View File

@ -4,6 +4,12 @@
margin-bottom: 60px;
}
.floatingTopButton {
position: absolute;
top: 70px;
right: 10px;
}
@media only screen and (max-width: 680px) {
.card {
width: 90%;

View File

@ -2,13 +2,15 @@ import Vue from 'vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtCard from '../../components/ft-card/ft-card.vue'
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'
export default Vue.extend({
name: 'Popular',
components: {
'ft-loader': FtLoader,
'ft-card': FtCard,
'ft-element-list': FtElementList
'ft-element-list': FtElementList,
'ft-icon-button': FtIconButton
},
data: function () {
return {
@ -16,35 +18,42 @@ export default Vue.extend({
shownResults: []
}
},
computed: {
popularCache: function () {
return this.$store.getters.getPopularCache
}
},
mounted: function () {
this.getTrendingInfo()
this.shownResults = this.popularCache
if (!this.shownResults || this.shownResults.length < 1) {
this.fetchPopularInfo()
}
},
methods: {
getTrendingInfo: function () {
this.isLoading = true
fetchPopularInfo: async function () {
const searchPayload = {
resource: 'popular',
id: '',
params: {}
}
this.$store.dispatch('invidiousAPICall', searchPayload).then((result) => {
if (!result) {
return
}
console.log(result)
const returnData = result.filter((item) => {
return item.type === 'video' || item.type === 'shortVideo' || item.type === 'channel' || item.type === 'playlist'
})
this.shownResults = this.shownResults.concat(returnData)
this.isLoading = false
}).catch((err) => {
this.isLoading = true
const result = await this.$store.dispatch('invidiousAPICall', searchPayload).catch((err) => {
console.log(err)
})
if (!result) {
this.isLoading = false
return
}
console.log(result)
this.shownResults = result.filter((item) => {
return item.type === 'video' || item.type === 'shortVideo' || item.type === 'channel' || item.type === 'playlist'
})
this.isLoading = false
this.$store.commit('setPopularCache', this.shownResults)
}
}
})

View File

@ -13,6 +13,14 @@
:data="shownResults"
/>
</ft-card>
<ft-icon-button
v-if="!isLoading"
icon="sync"
class="floatingTopButton"
:size="12"
theme="primary"
@click="fetchPopularInfo"
/>
</div>
</template>

View File

@ -138,9 +138,10 @@ export default Vue.extend({
if (video.uploaded_at !== null) {
publishDate = ytTrendScraper.calculate_published(video.uploaded_at, Date.now())
}
if (video.duration !== null) {
if (video.duration !== null && video.duration !== '') {
videoDuration = ytTrendScraper.calculate_length_in_seconds(video.duration)
}
authId = authId[0].replace(/(user|channel)\//, '')
returnDataInvidious.push(
{
videoId: videoId,

View File

@ -4,6 +4,12 @@
margin-bottom: 60px;
}
.floatingTopButton {
position: absolute;
top: 70px;
right: 10px;
}
@media only screen and (max-width: 680px) {
.card {
width: 90%;

View File

@ -2,6 +2,7 @@ import Vue from 'vue'
import FtCard from '../../components/ft-card/ft-card.vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'
import ytrend from 'yt-trending-scraper'
@ -10,7 +11,8 @@ export default Vue.extend({
components: {
'ft-card': FtCard,
'ft-loader': FtLoader,
'ft-element-list': FtElementList
'ft-element-list': FtElementList,
'ft-icon-button': FtIconButton
},
data: function () {
return {
@ -30,23 +32,34 @@ export default Vue.extend({
},
invidiousInstance: function () {
return this.$store.getters.getInvidiousInstance
},
trendingCache () {
return this.$store.getters.getTrendingCache
}
},
mounted: function () {
if (!this.usingElectron) {
this.getVideoInformationInvidious()
if (this.trendingCache && this.trendingCache.length > 0) {
this.shownResults = this.trendingCache
} else {
switch (this.backendPreference) {
case 'local':
this.getTrendingInfoLocal()
break
case 'invidious':
this.getTrendingInfoInvidious()
break
}
this.getTrendingInfo()
}
},
methods: {
getTrendingInfo () {
if (!this.usingElectron) {
this.getVideoInformationInvidious()
} else {
switch (this.backendPreference) {
case 'local':
this.getTrendingInfoLocal()
break
case 'invidious':
this.getTrendingInfoInvidious()
break
}
}
},
getTrendingInfoLocal: function () {
this.isLoading = true
@ -57,8 +70,9 @@ export default Vue.extend({
return item.type === 'video' || item.type === 'channel' || item.type === 'playlist'
})
this.shownResults = this.shownResults.concat(returnData)
this.shownResults = returnData
this.isLoading = false
this.$store.commit('setTrendingCache', this.shownResults)
}).catch((err) => {
console.log(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
@ -100,8 +114,9 @@ export default Vue.extend({
return item.type === 'video' || item.type === 'channel' || item.type === 'playlist'
})
this.shownResults = this.shownResults.concat(returnData)
this.shownResults = returnData
this.isLoading = false
this.$store.commit('setTrendingCache', this.shownResults)
}).catch((err) => {
console.log(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')

View File

@ -13,6 +13,14 @@
:data="shownResults"
/>
</ft-card>
<ft-icon-button
v-if="!isLoading"
icon="sync"
class="floatingTopButton"
:size="12"
theme="primary"
@click="getTrendingInfo"
/>
</div>
</template>

View File

@ -4,6 +4,7 @@ import xml2vtt from 'yt-xml2vtt'
import $ from 'jquery'
import fs from 'fs'
import electron from 'electron'
import ytDashGen from 'yt-dash-manifest-generator'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import FtCard from '../../components/ft-card/ft-card.vue'
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
@ -55,6 +56,7 @@ export default Vue.extend({
videoPublished: 0,
videoStoryboardSrc: '',
audioUrl: '',
dashSrc: [],
activeSourceList: [],
videoSourceList: [],
audioSourceList: [],
@ -139,23 +141,6 @@ export default Vue.extend({
youtubeNoCookieEmbeddedFrame: function () {
return `<iframe width='560' height='315' src='https://www.youtube-nocookie.com/embed/${this.videoId}?rel=0' frameborder='0' allow='autoplay; encrypted-media' allowfullscreen></iframe>`
},
dashSrc: function () {
let url = `${this.invidiousInstance}/api/manifest/dash/id/${this.videoId}.mpd`
if (this.proxyVideos || !this.usingElectron) {
url = url + '?local=true'
}
return [
{
url: url,
type: 'application/dash+xml',
label: 'Dash',
qualityLabel: 'Auto'
}
]
}
},
watch: {
@ -217,7 +202,7 @@ export default Vue.extend({
this.$store
.dispatch('ytGetVideoInformation', this.videoId)
.then(result => {
.then(async result => {
console.log(result)
this.videoTitle = result.videoDetails.title
this.videoViewCount = parseInt(
@ -241,6 +226,15 @@ export default Vue.extend({
this.videoDislikeCount = result.videoDetails.dislikes
this.isLive = result.player_response.videoDetails.isLiveContent
const captionTracks =
result.player_response.captions &&
result.player_response.captions.playerCaptionsTracklistRenderer
.captionTracks
if (typeof captionTracks !== 'undefined') {
await this.createCaptionUrls(captionTracks)
}
if (this.videoDislikeCount === null) {
this.videoDislikeCount = 0
}
@ -297,6 +291,7 @@ export default Vue.extend({
} else {
this.videoLengthSeconds = parseInt(result.videoDetails.lengthSeconds)
this.videoSourceList = result.player_response.streamingData.formats
this.dashSrc = await this.createLocalDashManifest(result.formats)
this.audioSourceList = result.player_response.streamingData.adaptiveFormats.filter((format) => {
return format.mimeType.includes('audio')
@ -321,15 +316,6 @@ export default Vue.extend({
this.createLocalStoryboardUrls(templateUrl)
}
const captionTracks =
result.player_response.captions &&
result.player_response.captions.playerCaptionsTracklistRenderer
.captionTracks
if (typeof captionTracks !== 'undefined') {
this.createCaptionUrls(captionTracks)
}
this.isLoading = false
})
.catch(err => {
@ -342,7 +328,7 @@ export default Vue.extend({
}
})
console.log(err)
if (!this.usingElectron || (this.backendPreference === 'local' && this.backendFallback)) {
if (!this.usingElectron || (this.backendPreference === 'local' && this.backendFallback && !err.includes('private'))) {
this.showToast({
message: this.$t('Falling back to Invidious API')
})
@ -619,6 +605,55 @@ export default Vue.extend({
}
},
createLocalDashManifest: function (formats) {
const xmlData = ytDashGen.generate_dash_file_from_formats(formats, this.videoLengthSeconds)
const userData = electron.remote.app.getPath('userData')
let fileLocation
let uriSchema
if (this.isDev) {
fileLocation = `dashFiles/${this.videoId}.xml`
uriSchema = fileLocation
// if the location does not exist, writeFileSync will not create the directory, so we have to do that manually
if (!fs.existsSync('dashFiles/')) {
fs.mkdirSync('dashFiles/')
}
} else {
fileLocation = `${userData}/dashFiles/${this.videoId}.xml`
uriSchema = `file://${fileLocation}`
if (!fs.existsSync(`${userData}/dashFiles/`)) {
fs.mkdirSync(`${userData}/dashFiles/`)
}
}
fs.writeFileSync(fileLocation, xmlData)
console.log('CREATED FILE')
return [
{
url: uriSchema,
type: 'application/dash+xml',
label: 'Dash',
qualityLabel: 'Auto'
}
]
},
createInvidiousDashManifest: function () {
let url = `${this.invidiousInstance}/api/manifest/dash/id/${this.videoId}.mpd`
if (this.proxyVideos || !this.usingElectron) {
url = url + '?local=true'
}
return [
{
url: url,
type: 'application/dash+xml',
label: 'Dash',
qualityLabel: 'Auto'
}
]
},
createLocalStoryboardUrls: function (templateUrl) {
const storyboards = templateUrl.split('|')
const storyboardArray = []
@ -653,11 +688,14 @@ export default Vue.extend({
if (this.isDev) {
fileLocation = `storyboards/${this.videoId}.vtt`
uriSchema = fileLocation
// if the location does not exist, writeFileSync will not create the directory, so we have to do that manually
if (!fs.existsSync('storyboards/')) {
fs.mkdirSync('storyboards/')
}
} else {
fileLocation = `${userData}/storyboards/${this.videoId}.vtt`
uriSchema = `file://${fileLocation}`
}
fs.writeFileSync(fileLocation, results)
this.videoStoryboardSrc = uriSchema
@ -700,9 +738,8 @@ export default Vue.extend({
if (this.rememberHistory && !this.isLoading && !this.isLive) {
const player = this.$refs.videoPlayer.player
if (typeof player !== 'undefined' && this.saveWatchedProgress) {
if (player !== null && this.saveWatchedProgress) {
const currentTime = this.$refs.videoPlayer.player.currentTime()
console.log(currentTime)
const payload = {
videoId: this.videoId,
watchProgress: currentTime

View File

@ -292,7 +292,7 @@ Video:
Views: Aufrufe
# Context is "X People Watching"
Watching: aktive Zuschauer
Watched: Aufrufe
Watched: Gesehen
# As in a Live Video
Live: Live
Live Now: Jetzt Live