Update/1.12.0 (#1227)
* Explain why we need custom CORS headers. * Translated using Weblate (German) Currently translated at 100.0% (170 of 170 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/de/ * Translated using Weblate (Alemannic) Currently translated at 100.0% (170 of 170 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/gsw/ * Bump svelte from 5.43.5 to 5.45.2 in /materialious Bumps [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) from 5.43.5 to 5.45.2. - [Release notes](https://github.com/sveltejs/svelte/releases) - [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md) - [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.45.2/packages/svelte) --- updated-dependencies: - dependency-name: svelte dependency-version: 5.45.2 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Bump vite from 7.2.4 to 7.2.6 in /materialious Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.2.4 to 7.2.6. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v7.2.6/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-version: 7.2.6 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump @capacitor/core from 7.4.3 to 7.4.4 in /materialious Bumps [@capacitor/core](https://github.com/ionic-team/capacitor) from 7.4.3 to 7.4.4. - [Release notes](https://github.com/ionic-team/capacitor/releases) - [Changelog](https://github.com/ionic-team/capacitor/blob/7.4.4/CHANGELOG.md) - [Commits](https://github.com/ionic-team/capacitor/compare/7.4.3...7.4.4) --- updated-dependencies: - dependency-name: "@capacitor/core" dependency-version: 7.4.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump shaka-player from 4.16.10 to 4.16.11 in /materialious Bumps [shaka-player](https://github.com/shaka-project/shaka-player) from 4.16.10 to 4.16.11. - [Release notes](https://github.com/shaka-project/shaka-player/releases) - [Changelog](https://github.com/shaka-project/shaka-player/blob/v4.16.11/CHANGELOG.md) - [Commits](https://github.com/shaka-project/shaka-player/compare/v4.16.10...v4.16.11) --- updated-dependencies: - dependency-name: shaka-player dependency-version: 4.16.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump human-number from 2.0.7 to 2.0.8 in /materialious Bumps [human-number](https://github.com/Kikobeats/human-number) from 2.0.7 to 2.0.8. - [Release notes](https://github.com/Kikobeats/human-number/releases) - [Changelog](https://github.com/Kikobeats/human-number/blob/master/CHANGELOG.md) - [Commits](https://github.com/Kikobeats/human-number/compare/v2.0.7...v2.0.8) --- updated-dependencies: - dependency-name: human-number dependency-version: 2.0.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Bump chokidar from 4.0.3 to 5.0.0 in /materialious/electron Bumps [chokidar](https://github.com/paulmillr/chokidar) from 4.0.3 to 5.0.0. - [Release notes](https://github.com/paulmillr/chokidar/releases) - [Commits](https://github.com/paulmillr/chokidar/compare/4.0.3...5.0.0) --- updated-dependencies: - dependency-name: chokidar dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump electron from 39.2.3 to 39.2.4 in /materialious/electron Bumps [electron](https://github.com/electron/electron) from 39.2.3 to 39.2.4. - [Release notes](https://github.com/electron/electron/releases) - [Commits](https://github.com/electron/electron/compare/v39.2.3...v39.2.4) --- updated-dependencies: - dependency-name: electron dependency-version: 39.2.4 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Translated using Weblate (German) Currently translated at 100.0% (172 of 172 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/de/ * Translated using Weblate (Alemannic) Currently translated at 100.0% (172 of 172 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/gsw/ * Translated using Weblate (Hungarian) Currently translated at 100.0% (172 of 172 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/hu/ * Add link to official RYD website * Translated using Weblate (Latvian) Currently translated at 73.2% (126 of 172 strings) Translation: Materialious/Materialious Translate-URL: https://toolate.othing.xyz/projects/materialious/materialious/lv/ * Bump version to 1.12.0 * Fix menu dropdown on theatre mode * Fixe linting * Update package-lock.json * Update package-lock.json * Update package-lock.json --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: mk-pmb <mk-pmb@users.noreply.github.com> Co-authored-by: Lenny Angst <lenny@familie-angst.ch> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me> Co-authored-by: ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) <toolate.othing.xyz.coool@privatepasta.com>
This commit is contained in:
@@ -1,24 +1,26 @@
|
||||
name: Check web
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
|
||||
jobs:
|
||||
web-check:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./materialious
|
||||
web-check:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./materialious
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: latest
|
||||
- name: Install modules
|
||||
run: npm install
|
||||
- name: Check linting
|
||||
run: npm run check
|
||||
- name: Attempt to build codebase
|
||||
run: npm run build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: latest
|
||||
- name: Install modules
|
||||
run: npm install
|
||||
- name: Run svelte checks
|
||||
run: npm run check
|
||||
- name: Check linting
|
||||
run: npm run eslint
|
||||
- name: Attempt to build codebase
|
||||
run: npm run build
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
- Sync your watch progress between Invidious sessions.
|
||||
- Watch sync parties.
|
||||
- Sponsorblock built-in.
|
||||
- Return YouTube dislikes built-in.
|
||||
- [Return YouTube Dislike](https://github.com/Anarios/return-youtube-dislike) (RYD) built-in.
|
||||
- [DeArrow](https://github.com/ajayyy/DeArrow) built-in (With local processing fallback).
|
||||
- No ads.
|
||||
- No tracking.
|
||||
|
||||
+11
-2
@@ -1,5 +1,14 @@
|
||||
# Setup
|
||||
For security reasons regarding CORS, your hosted instance of Materialious must serve as the value for the `Access-Control-Allow-Origin` header on Invidious.
|
||||
|
||||
### CORS
|
||||
To assure browsers they are allowed to access your Materialious instance
|
||||
despite their default [same-origin policy][wp-sop], the instance's webserver
|
||||
needs to send [cross-origin resource sharing (CORS)][wp-cors] headers in its
|
||||
response to the browser's `OPTIONS` request. The `Access-Control-Allow-Origin`
|
||||
header of that response must be set to the public origin URI of your instance.
|
||||
|
||||
[wp-sop]: https://en.wikipedia.org/wiki/Same-origin_policy
|
||||
[wp-cors]: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||
|
||||
Invidious doesn't provide a simple way to modify CORS, so this must be done with your reverse proxy.
|
||||
|
||||
@@ -169,7 +178,7 @@ services:
|
||||
# URL to your proxied Companion instance
|
||||
VITE_DEFAULT_COMPANION_INSTANCE: "https://companion.materialio.us"
|
||||
|
||||
# URL TO RYD
|
||||
# URL TO RYD (Return YouTube Dislike / https://github.com/Anarios/return-youtube-dislike)
|
||||
# Leave blank to disable completely.
|
||||
VITE_DEFAULT_RETURNYTDISLIKES_INSTANCE: "https://returnyoutubedislikeapi.com"
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "us.materialio.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 171
|
||||
versionName "1.11.10"
|
||||
versionCode 172
|
||||
versionName "1.12.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -68,7 +68,11 @@
|
||||
</content_rating>
|
||||
<releases>
|
||||
|
||||
<release version="1.11.10" date="2025-11-28">
|
||||
|
||||
<release version="1.12.0" date="2025-12-05">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.12.0</url>
|
||||
</release>
|
||||
<release version="1.11.10" date="2025-11-28">
|
||||
<url>https://github.com/Materialious/Materialious/releases/tag/1.11.10</url>
|
||||
</release>
|
||||
<release version="1.11.9" date="2025-11-25">
|
||||
|
||||
Generated
+16
-16
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.11.9",
|
||||
"version": "1.12.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "Materialious",
|
||||
"version": "1.11.9",
|
||||
"version": "1.12.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"chokidar": "~4.0.3",
|
||||
"chokidar": "~5.0.0",
|
||||
"electron-is-dev": "~2.0.0",
|
||||
"electron-serve": "~3.0.0",
|
||||
"electron-unhandled": "^4.0.1",
|
||||
@@ -21,7 +21,7 @@
|
||||
"jsonfile": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^39.2.3",
|
||||
"electron": "^39.2.4",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.3"
|
||||
@@ -1902,15 +1902,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
|
||||
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
"readdirp": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
@@ -2584,9 +2584,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "39.2.3",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-39.2.3.tgz",
|
||||
"integrity": "sha512-j7k7/bj3cNA29ty54FzEMRUoqirE+RBQPhPFP+XDuM93a1l2WcDPiYumxKWz+iKcXxBJLFdMIAlvtLTB/RfCkg==",
|
||||
"version": "39.2.4",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-39.2.4.tgz",
|
||||
"integrity": "sha512-KxPtwpFceQKSxRtUY39piHLYhJMMyHfOhc70e6zRnKGrbRdK6hzEqssth8IGjlKOdkeT4KCvIEngnNraYk39+g==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
@@ -4989,12 +4989,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
|
||||
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Materialious",
|
||||
"version": "1.11.10",
|
||||
"version": "1.12.0",
|
||||
"description": "Modern material design for Invidious.",
|
||||
"author": {
|
||||
"name": "Ward Pearce",
|
||||
@@ -24,7 +24,7 @@
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.0",
|
||||
"bgutils-js": "^3.2.0",
|
||||
"chokidar": "~4.0.3",
|
||||
"chokidar": "~5.0.0",
|
||||
"electron-is-dev": "~2.0.0",
|
||||
"electron-serve": "~3.0.0",
|
||||
"electron-unhandled": "^4.0.1",
|
||||
@@ -34,7 +34,7 @@
|
||||
"jsonfile": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^39.2.3",
|
||||
"electron": "^39.2.4",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-rebuild": "^3.2.9",
|
||||
"typescript": "^5.9.3"
|
||||
|
||||
@@ -57,7 +57,7 @@ export default ts.config(
|
||||
'.DS_Store',
|
||||
'node_modules',
|
||||
'/build',
|
||||
'/.svelte-kit',
|
||||
'**/.svelte-kit/*',
|
||||
'/package',
|
||||
'.env',
|
||||
'.env.*',
|
||||
@@ -65,7 +65,14 @@ export default ts.config(
|
||||
// Ignore files for PNPM, NPM and YARN
|
||||
'pnpm-lock.yaml',
|
||||
'package-lock.json',
|
||||
'yarn.lock'
|
||||
'yarn.lock',
|
||||
// Ignore our nodejs android code
|
||||
'**/nodejs-android/*',
|
||||
// Ignore electron code from capacitorjs
|
||||
'**/electron/*',
|
||||
// Ignore build files
|
||||
'**/build/*',
|
||||
'**/android/app/src/main/assets/*'
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
Generated
+30
-30
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.11.9",
|
||||
"version": "1.12.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "materialious",
|
||||
"version": "1.11.9",
|
||||
"version": "1.12.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@capacitor-community/electron": "^5.0.1",
|
||||
@@ -15,7 +15,7 @@
|
||||
"@capacitor/app": "^7.1.0",
|
||||
"@capacitor/browser": "^7.0.0",
|
||||
"@capacitor/clipboard": "^7.0.0",
|
||||
"@capacitor/core": "^7.4.3",
|
||||
"@capacitor/core": "^7.4.4",
|
||||
"@capacitor/preferences": "^7.0.2",
|
||||
"@capacitor/screen-orientation": "^7.0.0",
|
||||
"@capacitor/share": "^7.0.2",
|
||||
@@ -28,7 +28,7 @@
|
||||
"fuse.js": "^7.0.0",
|
||||
"googlevideo": "^4.0.4",
|
||||
"he": "^1.2.0",
|
||||
"human-number": "^2.0.7",
|
||||
"human-number": "^2.0.8",
|
||||
"i18next": "^25.6.3",
|
||||
"iso-3166": "^4.4.0",
|
||||
"iso-639-1": "^3.1.5",
|
||||
@@ -36,7 +36,7 @@
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.16.9",
|
||||
"shaka-player": "^4.16.11",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
"youtubei.js": "^16.0.1"
|
||||
@@ -59,12 +59,12 @@
|
||||
"patch-package": "^8.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.43.5",
|
||||
"svelte": "^5.45.2",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.47.0",
|
||||
"vite": "^7.2.4"
|
||||
"vite": "^7.2.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -2067,9 +2067,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-wCWr8fQ9Wxn0466vPg7nMn0tivbNVjNy1yL4GvDSIZuZx7UpU2HeVGNe9QjN/quEd+YLRFeKEBLBw619VqUiNg==",
|
||||
"version": "7.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.4.tgz",
|
||||
"integrity": "sha512-xzjxpr+d2zwTpCaN0k+C6wKSZzWFAb9OVEUtmO72ihjr/NEDoLvsGl4WLfjWPcCO2zOy0b2X52tfRWjECFUjtw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -5664,10 +5664,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/devalue": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz",
|
||||
"integrity": "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==",
|
||||
"dev": true,
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.5.0.tgz",
|
||||
"integrity": "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dezalgo": {
|
||||
@@ -6281,9 +6280,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esrap": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.2.tgz",
|
||||
"integrity": "sha512-DgvlIQeowRNyvLPWW4PT7Gu13WznY288Du086E751mwwbsgr29ytBiYeLzAGIo0qk3Ujob0SDk8TiSaM5WQzNg==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.0.tgz",
|
||||
"integrity": "sha512-WBmtxe7R9C5mvL4n2le8nMUe4mD5V9oiK2vJpQ9I3y20ENPUomPcphBXE8D1x/Bm84oN1V+lOfgXxtqmxTp3Xg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
@@ -7331,9 +7330,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/human-number": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/human-number/-/human-number-2.0.7.tgz",
|
||||
"integrity": "sha512-oRlIx8WSLqpGutVzCq72WipnfH1+OaSoxiPc5l2eMxjqgGow3K4jzCxAHkS93nPxFDa0vXUKaDrmdIAKLwBlHQ==",
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/human-number/-/human-number-2.0.8.tgz",
|
||||
"integrity": "sha512-0OikVKOKQR86Plj4Oyszl4TNYu4a9dsKeZKaZw6uHw+7zCDXZ3E3ldG/3ZRddwRajYljdZsMKFcvrNNXHR6wVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"round-to": "~5.0.0"
|
||||
@@ -10997,9 +10996,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/shaka-player": {
|
||||
"version": "4.16.10",
|
||||
"resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-4.16.10.tgz",
|
||||
"integrity": "sha512-FJJk3rbV6IQ/gmdB6EZ4q4VuCKXdWG1pf7dPuqfZi6lNWIvymT4YWE+Hv5qkBwJRtT0L/8p/EFJKMhwE4AMTMQ==",
|
||||
"version": "4.16.11",
|
||||
"resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-4.16.11.tgz",
|
||||
"integrity": "sha512-e87a3KtI69duaAm1omY2HwN9hq72ZN0j6mc4aBQgTrfJIBG8hZAw34tEPo6oqGR3IBpK86ASTmtrdUXCzt6yjg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -11692,9 +11691,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte": {
|
||||
"version": "5.43.5",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.43.5.tgz",
|
||||
"integrity": "sha512-HQoZArIewxQVNedseDsgMgnRSC4XOXczxXLF9rOJaPIJkg58INOPUiL8aEtzqZIXNSZJyw8NmqObwg/voajiHQ==",
|
||||
"version": "5.45.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.45.2.tgz",
|
||||
"integrity": "sha512-yyXdW2u3H0H/zxxWoGwJoQlRgaSJLp+Vhktv12iRw2WRDlKqUPT54Fi0K/PkXqrdkcQ98aBazpy0AH4BCBVfoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
@@ -11705,8 +11704,9 @@
|
||||
"aria-query": "^5.3.1",
|
||||
"axobject-query": "^4.1.0",
|
||||
"clsx": "^2.1.1",
|
||||
"devalue": "^5.5.0",
|
||||
"esm-env": "^1.2.1",
|
||||
"esrap": "^2.1.0",
|
||||
"esrap": "^2.2.0",
|
||||
"is-reference": "^3.0.3",
|
||||
"locate-character": "^3.0.0",
|
||||
"magic-string": "^0.30.11",
|
||||
@@ -12500,9 +12500,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "7.2.4",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz",
|
||||
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
|
||||
"integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "materialious",
|
||||
"version": "1.11.10",
|
||||
"version": "1.12.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -32,12 +32,12 @@
|
||||
"patch-package": "^8.0.1",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-svelte": "^3.4.0",
|
||||
"svelte": "^5.43.5",
|
||||
"svelte": "^5.45.2",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.47.0",
|
||||
"vite": "^7.2.4"
|
||||
"vite": "^7.2.6"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
@@ -47,7 +47,7 @@
|
||||
"@capacitor/app": "^7.1.0",
|
||||
"@capacitor/browser": "^7.0.0",
|
||||
"@capacitor/clipboard": "^7.0.0",
|
||||
"@capacitor/core": "^7.4.3",
|
||||
"@capacitor/core": "^7.4.4",
|
||||
"@capacitor/preferences": "^7.0.2",
|
||||
"@capacitor/screen-orientation": "^7.0.0",
|
||||
"@capacitor/share": "^7.0.2",
|
||||
@@ -60,7 +60,7 @@
|
||||
"fuse.js": "^7.0.0",
|
||||
"googlevideo": "^4.0.4",
|
||||
"he": "^1.2.0",
|
||||
"human-number": "^2.0.7",
|
||||
"human-number": "^2.0.8",
|
||||
"i18next": "^25.6.3",
|
||||
"iso-3166": "^4.4.0",
|
||||
"iso-639-1": "^3.1.5",
|
||||
@@ -68,7 +68,7 @@
|
||||
"media-captions": "^1.0.4",
|
||||
"mousetrap": "^1.6.5",
|
||||
"peerjs": "^1.5.5",
|
||||
"shaka-player": "^4.16.9",
|
||||
"shaka-player": "^4.16.11",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-infinite-loading": "^1.4.0",
|
||||
"youtubei.js": "^16.0.1"
|
||||
|
||||
@@ -47,7 +47,7 @@ if (Capacitor.getPlatform() === 'android') {
|
||||
if (needsProxying(args[1])) {
|
||||
args[1] = corsProxyUrl + args[1];
|
||||
}
|
||||
/* @ts-ignore */
|
||||
// @ts-expect-error args have any type
|
||||
return originalXhrOpen.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,7 +52,9 @@ export async function fetchErrorHandle(response: Response): Promise<Response> {
|
||||
try {
|
||||
const json = await response.json();
|
||||
message = 'errorBacktrace' in json ? json.errorBacktrace : json.error;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
throw Error(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ export interface HashTag {
|
||||
videoCount: number;
|
||||
}
|
||||
|
||||
export interface Notification extends VideoBase {}
|
||||
export type Notification = VideoBase;
|
||||
|
||||
export interface Feed {
|
||||
notifications: Notification[];
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
|
||||
let snackBarAlert = $state('');
|
||||
let originalOrigination: ScreenOrientationResult | undefined;
|
||||
// eslint-disable-next-line no-undef
|
||||
let watchProgressTimeout: NodeJS.Timeout;
|
||||
let showVideoRetry = $state(false);
|
||||
|
||||
@@ -303,7 +304,9 @@
|
||||
|
||||
try {
|
||||
document.getElementsByClassName('shaka-ad-info')[0].remove();
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
if (!data.video.liveNow) {
|
||||
if (watchProgressTimeout) {
|
||||
@@ -525,7 +528,7 @@
|
||||
console.error('Player error:', error);
|
||||
});
|
||||
|
||||
player.getNetworkingEngine()?.registerResponseFilter((type, response, _) => {
|
||||
player.getNetworkingEngine()?.registerResponseFilter((type, response) => {
|
||||
if (
|
||||
type !== shaka.net.NetworkingEngine.RequestType.SEGMENT ||
|
||||
!response.uri.includes('/api/timedtext')
|
||||
@@ -746,12 +749,16 @@
|
||||
if (playerPos && Number(playerPos) > toSetTime) {
|
||||
toSetTime = Number(playerPos);
|
||||
}
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
if ($synciousStore && $synciousInstanceStore && $authStore) {
|
||||
try {
|
||||
toSetTime = (await getVideoProgress(data.video.videoId))[0].time;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
return toSetTime;
|
||||
@@ -769,7 +776,9 @@
|
||||
) {
|
||||
try {
|
||||
localStorage.setItem(`v_${data.video.videoId}`, playerElement.currentTime.toString());
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
if (synciousEnabled) {
|
||||
saveVideoProgress(data.video.videoId, playerElement.currentTime);
|
||||
@@ -777,7 +786,9 @@
|
||||
} else {
|
||||
try {
|
||||
localStorage.removeItem(`v_${data.video.videoId}`);
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
if (synciousEnabled) {
|
||||
deleteVideoProgress(data.video.videoId);
|
||||
@@ -799,7 +810,9 @@
|
||||
|
||||
try {
|
||||
savePlayerPos();
|
||||
} catch (error) {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
Mousetrap.unbind(['left', 'right', 'space', 'c', 'f', 'shift+left', 'shift+right']);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
let showSearchBox = $state(false);
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let debounceTimer: NodeJS.Timeout;
|
||||
function debouncedSearch(event: any) {
|
||||
if (!searchSuggestions) return;
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
events.events.forEach((event) => {
|
||||
if (event.type === 'change-video' && event.videoId) {
|
||||
currentUrl.pathname = resolve(`/watch/[videoId]`, { videoId: event.videoId });
|
||||
// eslint-disable-next-line svelte/no-navigation-without-resolve
|
||||
goto(currentUrl);
|
||||
} else if (event.type === 'goto' && event.path && event.path !== $page.url.pathname) {
|
||||
if (blockedPages.includes(event.path.replace('/', ''))) {
|
||||
ui('#sync-party-private-page');
|
||||
} else {
|
||||
currentUrl.pathname = event.path;
|
||||
// eslint-disable-next-line svelte/no-navigation-without-resolve
|
||||
goto(currentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,9 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
const img = await insecureRequestImageHandler(imageSrc);
|
||||
@@ -107,7 +109,9 @@
|
||||
if (get(synciousStore) && get(synciousInstanceStore) && get(authStore)) {
|
||||
try {
|
||||
progress = (await queueSyncious(video.videoId))?.time?.toString() ?? undefined;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -156,6 +160,7 @@
|
||||
|
||||
<div class:sideways-root={sideways} tabindex="0" role="button">
|
||||
<div id="thumbnail-container">
|
||||
<!-- eslint-disable svelte/no-navigation-without-resolve -->
|
||||
<a
|
||||
tabindex="-1"
|
||||
class="wave thumbnail"
|
||||
|
||||
@@ -48,10 +48,13 @@
|
||||
|
||||
isLoading = true;
|
||||
transcript = null;
|
||||
const resp = await fetch(`${!video.fallbackPatch ? new URL(get(instanceStore)).origin : ''}${url}`);
|
||||
const resp = await fetch(
|
||||
`${!video.fallbackPatch ? new URL(get(instanceStore)).origin : ''}${url}`
|
||||
);
|
||||
transcript = await parseText(await resp.text(), { strict: false });
|
||||
|
||||
// Group cues by Math.ceil(startTime)
|
||||
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
||||
const startTimeMap = new Map<number, VTTCue[]>();
|
||||
for (const cue of transcript.cues) {
|
||||
const roundedTime = Math.ceil(cue.startTime);
|
||||
@@ -98,7 +101,7 @@
|
||||
<div class="field label suffix border">
|
||||
<select bind:value={url} onchange={loadTranscript} name="captions">
|
||||
<option selected={true} value={null}>{$_('selectLang')}</option>
|
||||
{#each video.captions as caption}
|
||||
{#each video.captions as caption (caption)}
|
||||
<option value={caption.url}>{caption.label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
@@ -131,7 +134,7 @@
|
||||
{:else if transcript}
|
||||
{#if transcript.cues.length > 0}
|
||||
{#if transcriptCues.length > 0}
|
||||
{#each transcriptCues as cue}
|
||||
{#each transcriptCues as cue (cue)}
|
||||
<div
|
||||
class="transcript-line"
|
||||
id={`transcript-line-${cue.startTime}`}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<h4>{$_('contributors')}</h4>
|
||||
|
||||
<div class="grid">
|
||||
{#each ghContributors as contributor}
|
||||
{#each ghContributors as contributor (contributor)}
|
||||
{#if contributor.type === 'User'}
|
||||
<div class="s12 m4 l4">
|
||||
<article>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
onchange={() => playerDefaultLanguage.set(defaultLanguage)}
|
||||
>
|
||||
<option selected={$playerDefaultLanguage === 'original'} value="original">Original</option>
|
||||
{#each languageNames as language}
|
||||
{#each languageNames as language (language)}
|
||||
<option selected={$playerDefaultLanguage === language} value={language}
|
||||
>{titleCase(language)}</option
|
||||
>
|
||||
@@ -113,7 +113,7 @@
|
||||
bind:value={$playerDefaultPlaybackSpeed}
|
||||
onchange={onSpeedChange}
|
||||
>
|
||||
{#each playbackRates as speed}
|
||||
{#each playbackRates as speed (speed)}
|
||||
<option value={speed}>x{speed}</option>
|
||||
{/each}
|
||||
</select>
|
||||
@@ -304,7 +304,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerStatisticsByDefault}
|
||||
onclick={() => playerStatisticsByDefault.set(!playerStatisticsByDefault)}
|
||||
onclick={() => playerStatisticsByDefault.set(!$playerStatisticsByDefault)}
|
||||
role="switch"
|
||||
/>
|
||||
<span></span>
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
</a>
|
||||
{/each}
|
||||
{#if !$isAndroidTvStore}
|
||||
<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
|
||||
<a href={`${$instanceStore}/preferences`} target="_blank" referrerpolicy="no-referrer">
|
||||
<i>
|
||||
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
sort_by: 'top',
|
||||
source: 'youtube'
|
||||
});
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
function commentTimestamps(html: string): string {
|
||||
@@ -71,7 +73,9 @@
|
||||
<span class="secondary-text">{comment.publishedText}</span>
|
||||
</a>
|
||||
<p class="no-margin">
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
{@html commentTimestamps(comment.contentHtml)}
|
||||
<!-- Comment comes directly from YT so is already sanitized -->
|
||||
</p>
|
||||
<div class="comment-actions">
|
||||
<p class="no-margin no-padding"><i>thumb_up</i> {numberWithCommas(comment.likeCount)}</p>
|
||||
@@ -95,7 +99,7 @@
|
||||
{/if}
|
||||
|
||||
{#if replies}
|
||||
{#each replies.comments as reply}
|
||||
{#each replies.comments as reply (reply)}
|
||||
<CommentSelf comment={reply} {videoId} isSubComp={true} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
<div class="space"></div>
|
||||
<div class="medium scroll">
|
||||
<div style="white-space: pre-line; overflow-wrap: break-word;">
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
{@html description}
|
||||
<!-- Description comes directly from YT so is already sanitized -->
|
||||
</div>
|
||||
|
||||
{#if video.keywords && video.keywords.length > 0}
|
||||
|
||||
@@ -71,6 +71,11 @@ dialog {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
menu {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1000px) {
|
||||
menu.mobile {
|
||||
position: fixed !important;
|
||||
|
||||
@@ -237,7 +237,9 @@ function setStores(toSet: Record<string, any>) {
|
||||
let userOverwritten: boolean = false;
|
||||
try {
|
||||
userOverwritten = localStorage.getItem(store.name) !== null;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
const paramValue = toSet[store.name];
|
||||
if (typeof paramValue !== 'undefined' && !userOverwritten) {
|
||||
@@ -284,7 +286,7 @@ export function bookmarkletSaveToUrl(): string {
|
||||
const url = new URL(location.origin);
|
||||
|
||||
persistedStores.forEach((store) => {
|
||||
let value = get(store.store);
|
||||
const value = get(store.store);
|
||||
if (value !== null && value !== undefined) {
|
||||
url.searchParams.set(store.name, value.toString());
|
||||
}
|
||||
|
||||
@@ -46,7 +46,9 @@ async function loadDayjsLocale(localeName: string) {
|
||||
try {
|
||||
const { default: locale } = await import(`dayjs/locale/${localeName}`);
|
||||
dayjs.locale(locale);
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
export async function initI18n(selectedLocale: string = getUserLocale()): Promise<void> {
|
||||
|
||||
@@ -77,7 +77,8 @@
|
||||
"materialiousLink": "Materialious-Link kopieren",
|
||||
"invidiousRedirect": "Invidious-Weiterleitungslink kopieren",
|
||||
"youtubeLink": "YouTube-Link kopieren",
|
||||
"includeTimestamp": "Mit Zeitstempel"
|
||||
"includeTimestamp": "Mit Zeitstempel",
|
||||
"copiedSuccess": "In Zwischenablage kopiert"
|
||||
},
|
||||
"download": "Herunterladen",
|
||||
"downloadSteps": {
|
||||
@@ -178,7 +179,8 @@
|
||||
"companionUrl": "Companion URL",
|
||||
"expandChapters": "Kapitel standardmäßig ausklappen",
|
||||
"displayThumbnailAvatars": "Vorschaubild-Avatare (Langsam)",
|
||||
"about": "Über"
|
||||
"about": "Über",
|
||||
"androidNativeShare": "Natives Teilen nutzen"
|
||||
},
|
||||
"subscribe": "Abonnieren",
|
||||
"recommendedVideos": "Vorgeschlagene Videos",
|
||||
@@ -200,5 +202,8 @@
|
||||
"duration": "Dauer",
|
||||
"sortBy": "Sortieren nach",
|
||||
"features": "Eigenschaften"
|
||||
}
|
||||
},
|
||||
"newest": "Neuste",
|
||||
"oldest": "Älteste",
|
||||
"popular": "Populär"
|
||||
}
|
||||
|
||||
@@ -87,7 +87,8 @@
|
||||
"displayThumbnailAvatars": "Vorschaubild-Avatar (Langsam)",
|
||||
"expandDescription": "Beschriibig standardmässig erwiitere",
|
||||
"disableAutoUpdate": "Automatischi Updates deaktiviere",
|
||||
"about": "Über"
|
||||
"about": "Über",
|
||||
"androidNativeShare": "Nativs Teile bruche"
|
||||
},
|
||||
"videos": "Videos",
|
||||
"cancel": "Abbreche",
|
||||
@@ -160,7 +161,8 @@
|
||||
"materialiousLink": "Materialious-Link kopiere",
|
||||
"youtubeLink": "YouTube-Link kopiere",
|
||||
"invidiousRedirect": "Invidious-Wiiterleitigslink kopiere",
|
||||
"includeTimestamp": "Mit Ziitstempel"
|
||||
"includeTimestamp": "Mit Ziitstempel",
|
||||
"copiedSuccess": "I d Zwüscheablaag kopiert"
|
||||
},
|
||||
"download": "Abelade",
|
||||
"downloadSteps": {
|
||||
@@ -200,5 +202,8 @@
|
||||
"duration": "Duur",
|
||||
"sortBy": "Sortiere nach",
|
||||
"features": "Eigeschafte"
|
||||
}
|
||||
},
|
||||
"newest": "Neusti",
|
||||
"oldest": "Ältisti",
|
||||
"popular": "Populär"
|
||||
}
|
||||
|
||||
@@ -108,7 +108,8 @@
|
||||
},
|
||||
"logout": "Kijelentkezés",
|
||||
"companionUrl": "Kiegészítő webcím",
|
||||
"about": "Névjegy"
|
||||
"about": "Névjegy",
|
||||
"androidNativeShare": "Natív megosztás használata"
|
||||
},
|
||||
"enabled": "Engedélyezve",
|
||||
"donate": "Adományozás",
|
||||
@@ -122,7 +123,8 @@
|
||||
"title": "Megosztás",
|
||||
"materialiousLink": "Materialious-hivatkozás megosztása",
|
||||
"youtubeLink": "Youtube-hivatkozás másolása",
|
||||
"invidiousRedirect": "Invidious átirányítási hivatkozás másolása"
|
||||
"invidiousRedirect": "Invidious átirányítási hivatkozás másolása",
|
||||
"copiedSuccess": "Vágólapra másolva"
|
||||
},
|
||||
"audioOnly": "Csak hang",
|
||||
"theatreMode": "Szélesvásznú mód",
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
"theme": {
|
||||
"theme": "Motīvs",
|
||||
"color": "Krāsa",
|
||||
"darkMode": "Tumšais režīms",
|
||||
"lightMode": "Gaišais režīms",
|
||||
"darkMode": "Tumšais motīvs",
|
||||
"lightMode": "Gaišais motīvs",
|
||||
"AmoledTheme": "AMOLED motīvs"
|
||||
},
|
||||
"player": {
|
||||
@@ -55,7 +55,10 @@
|
||||
"youtubeJsAlways": "Vienmēr izmantot",
|
||||
"localVideoFallback": "Vietējais video ieguves rezerves variants",
|
||||
"youtubeJsFallback": "Vietējais video apstrādes rezerves variants",
|
||||
"alwaysLoopVideo": "Vienmēr atskaņot (malt) uz riņķi video"
|
||||
"alwaysLoopVideo": "Vienmēr atskaņot (malt) uz riņķi video",
|
||||
"miniPlayer": "Mini atskaņotājs",
|
||||
"playerStatistics": "Rādīt atskaņotāja statistiku pēc noklusējuma",
|
||||
"autoPlayNextByDefault": "Automātiski atskaņot nākamo video pēc noklusējuma"
|
||||
},
|
||||
"deArrow": {
|
||||
"titleOnly": "Tikai virsrakstu",
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
import { get } from "svelte/store";
|
||||
import type { Image } from "./api/model";
|
||||
import { instanceStore } from "./store";
|
||||
import { get } from 'svelte/store';
|
||||
import type { Image } from './api/model';
|
||||
import { instanceStore } from './store';
|
||||
|
||||
export function getBestThumbnail(
|
||||
images: Image[] | null,
|
||||
maxWidthDimension: number = 480,
|
||||
maxHeightDimension = 360
|
||||
images: Image[] | null,
|
||||
maxWidthDimension: number = 480,
|
||||
maxHeightDimension = 360
|
||||
): string {
|
||||
if (images && images.length > 0) {
|
||||
const imagesFiltered = images.filter(
|
||||
(image) => image.width < maxWidthDimension && image.height < maxHeightDimension
|
||||
);
|
||||
if (images && images.length > 0) {
|
||||
const imagesFiltered = images.filter(
|
||||
(image) => image.width < maxWidthDimension && image.height < maxHeightDimension
|
||||
);
|
||||
|
||||
if (imagesFiltered.length === 0) {
|
||||
return images[0].url;
|
||||
}
|
||||
if (imagesFiltered.length === 0) {
|
||||
return images[0].url;
|
||||
}
|
||||
|
||||
imagesFiltered.sort((a, b) => {
|
||||
return b.width * b.height - a.width * a.height;
|
||||
});
|
||||
imagesFiltered.sort((a, b) => {
|
||||
return b.width * b.height - a.width * a.height;
|
||||
});
|
||||
|
||||
return imagesFiltered[0].url;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return imagesFiltered[0].url;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function proxyGoogleImage(source: string): string {
|
||||
if (source.startsWith('//')) source = `https:${source}`;
|
||||
if (source.startsWith('//')) source = `https:${source}`;
|
||||
|
||||
let path: string | undefined;
|
||||
try {
|
||||
path = new URL(source).pathname;
|
||||
} catch { }
|
||||
let path: string | undefined;
|
||||
try {
|
||||
path = new URL(source).pathname;
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
|
||||
if (typeof path === 'undefined') return '';
|
||||
if (typeof path === 'undefined') return '';
|
||||
|
||||
return `${get(instanceStore)}/ggpht${path}`;
|
||||
}
|
||||
return `${get(instanceStore)}/ggpht${path}`;
|
||||
}
|
||||
|
||||
@@ -1,61 +1,55 @@
|
||||
import { get } from "svelte/store";
|
||||
import { interfaceForceCase } from "./store";
|
||||
import { get } from 'svelte/store';
|
||||
import { interfaceForceCase } from './store';
|
||||
|
||||
export type TitleCase = 'uppercase' | 'lowercase' | 'sentence case' | 'title case' | null;
|
||||
export const titleCases: TitleCase[] = [
|
||||
'lowercase',
|
||||
'uppercase',
|
||||
'title case',
|
||||
'sentence case'
|
||||
];
|
||||
export const titleCases: TitleCase[] = ['lowercase', 'uppercase', 'title case', 'sentence case'];
|
||||
|
||||
export function letterCase(text: string, caseTypeOverwrite?: TitleCase): string {
|
||||
const casing = caseTypeOverwrite ? caseTypeOverwrite : get(interfaceForceCase);
|
||||
if (!casing) return text;
|
||||
const casing = caseTypeOverwrite ? caseTypeOverwrite : get(interfaceForceCase);
|
||||
if (!casing) return text;
|
||||
|
||||
switch (casing) {
|
||||
case 'lowercase':
|
||||
return text.toLowerCase();
|
||||
case 'uppercase':
|
||||
return text.toUpperCase();
|
||||
case 'sentence case':
|
||||
return sentenceCase(text);
|
||||
default:
|
||||
return titleCase(text);
|
||||
}
|
||||
switch (casing) {
|
||||
case 'lowercase':
|
||||
return text.toLowerCase();
|
||||
case 'uppercase':
|
||||
return text.toUpperCase();
|
||||
case 'sentence case':
|
||||
return sentenceCase(text);
|
||||
default:
|
||||
return titleCase(text);
|
||||
}
|
||||
}
|
||||
|
||||
export function sentenceCase(text: string): string {
|
||||
let sentences: string[] = text.match(/[^.!?]*[.!?]*/g) || [];
|
||||
const sentences: string[] = text.match(/[^.!?]*[.!?]*/g) || [];
|
||||
|
||||
let casedSentences: string[] = sentences.map(sentence => {
|
||||
sentence = sentence.trim();
|
||||
if (sentence.length === 0) return '';
|
||||
return sentence.charAt(0).toUpperCase() + sentence.slice(1).toLowerCase();
|
||||
});
|
||||
const casedSentences: string[] = sentences.map((sentence) => {
|
||||
sentence = sentence.trim();
|
||||
if (sentence.length === 0) return '';
|
||||
return sentence.charAt(0).toUpperCase() + sentence.slice(1).toLowerCase();
|
||||
});
|
||||
|
||||
return casedSentences.join(' ');
|
||||
return casedSentences.join(' ');
|
||||
}
|
||||
|
||||
export function titleCase(text: string): string {
|
||||
if (!text) return '';
|
||||
if (!text) return '';
|
||||
|
||||
let words: string[] = text.split(/(\s+)/).filter(word => word.trim().length > 0);
|
||||
const words: string[] = text.split(/(\s+)/).filter((word) => word.trim().length > 0);
|
||||
|
||||
let titleCasedWords: string[] = words.map(word => {
|
||||
if (word.length === 0) return '';
|
||||
const titleCasedWords: string[] = words.map((word) => {
|
||||
if (word.length === 0) return '';
|
||||
|
||||
const firstChar = word.charAt(0);
|
||||
const restOfWord = word.slice(1).toLowerCase();
|
||||
const firstChar = word.charAt(0);
|
||||
const restOfWord = word.slice(1).toLowerCase();
|
||||
|
||||
// Capitalize if the first character is a letter
|
||||
if (/[a-zA-Z]/.test(firstChar)) {
|
||||
return firstChar.toUpperCase() + restOfWord;
|
||||
}
|
||||
// Capitalize if the first character is a letter
|
||||
if (/[a-zA-Z]/.test(firstChar)) {
|
||||
return firstChar.toUpperCase() + restOfWord;
|
||||
}
|
||||
|
||||
return word;
|
||||
});
|
||||
return word;
|
||||
});
|
||||
|
||||
return titleCasedWords.join(' ');
|
||||
return titleCasedWords.join(' ');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { pushState } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import he from 'he';
|
||||
import type Peer from 'peerjs';
|
||||
import { get } from 'svelte/store';
|
||||
import { instanceStore, interfaceAllowInsecureRequests, isAndroidTvStore } from './store';
|
||||
import { interfaceAllowInsecureRequests, isAndroidTvStore } from './store';
|
||||
import type {
|
||||
Channel,
|
||||
HashTag,
|
||||
@@ -14,9 +13,10 @@ import type {
|
||||
Video,
|
||||
VideoBase
|
||||
} from './api/model';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export function isVideoID(videoId: string): boolean {
|
||||
var regExp = /^[a-zA-Z0-9_-]{11}$/;
|
||||
const regExp = /^[a-zA-Z0-9_-]{11}$/;
|
||||
return regExp.test(videoId);
|
||||
}
|
||||
|
||||
@@ -34,15 +34,15 @@ export function unsafeRandomItem(array: any[]): any {
|
||||
}
|
||||
|
||||
export function setWindowQueryFlag(key: string, value: string) {
|
||||
const currentPage = get(page);
|
||||
currentPage.url.searchParams.set(key, value);
|
||||
pushState(currentPage.url, currentPage.state);
|
||||
page.url.searchParams.set(key, value);
|
||||
// eslint-disable-next-line svelte/no-navigation-without-resolve
|
||||
pushState(page.url, page.state);
|
||||
}
|
||||
|
||||
export function removeWindowQueryFlag(key: string) {
|
||||
const currentPage = get(page);
|
||||
currentPage.url.searchParams.delete(key);
|
||||
pushState(currentPage.url, currentPage.state);
|
||||
page.url.searchParams.delete(key);
|
||||
// eslint-disable-next-line svelte/no-navigation-without-resolve
|
||||
pushState(page.url, page.state);
|
||||
}
|
||||
|
||||
let PeerInstance: typeof Peer;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { interfaceRegionStore, poTokenCacheStore } from '$lib/store';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { USER_AGENT } from 'bgutils-js';
|
||||
import { get } from 'svelte/store';
|
||||
import type { Types, Misc } from 'youtubei.js';
|
||||
import type { Types } from 'youtubei.js';
|
||||
import { Innertube, UniversalCache, Utils, YT, YTNodes, Platform } from 'youtubei.js';
|
||||
|
||||
Platform.shim.eval = async (
|
||||
|
||||
@@ -8,7 +8,7 @@ import { darkModeStore, interfaceAmoledTheme } from './store';
|
||||
export async function getDynamicTheme(mode?: string): Promise<Record<string, string>> {
|
||||
const givenSettings = await ui('theme');
|
||||
|
||||
// @ts-ignore
|
||||
// @ts-expect-error Works as expected
|
||||
const themes: string = givenSettings[mode ? mode : (ui('mode') as string)];
|
||||
const themeVars: Record<string, string> = {};
|
||||
themes.split(';').forEach((keyVar) => {
|
||||
|
||||
@@ -62,7 +62,9 @@ export async function getWatchDetails(videoId: string, url: URL) {
|
||||
returnYTDislikes = get(returnYtDislikesStore)
|
||||
? getDislikes(videoId, { priority: 'low' })
|
||||
: null;
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
const playlistId = url.searchParams.get('playlist');
|
||||
|
||||
@@ -119,7 +119,9 @@
|
||||
|
||||
async function login() {
|
||||
if (!$isAndroidTvStore) {
|
||||
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
||||
const path = new URL(`${get(instanceStore)}/authorize_token`);
|
||||
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
||||
const searchParams = new URLSearchParams({
|
||||
scopes: ':feed,:subscriptions*,:playlists*,:history*,:notifications*'
|
||||
});
|
||||
@@ -207,7 +209,9 @@
|
||||
const colorPalette = await colorTheme.getColorPalette();
|
||||
themeHex = convertToHexColorCode(colorPalette.primary);
|
||||
await ui('theme', themeHex);
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +266,7 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
||||
{@html webManifestLink}
|
||||
|
||||
{#if Capacitor.getPlatform() === 'android' && !$isAndroidTvStore}
|
||||
@@ -284,7 +289,7 @@
|
||||
>
|
||||
<Logo />
|
||||
</header>
|
||||
{#each getPages() as navPage}
|
||||
{#each getPages() as navPage (navPage)}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a href={resolve(navPage.href, {})} class:active={$page.url.href.endsWith(navPage.href)}
|
||||
><i>{navPage.icon}</i>
|
||||
@@ -361,7 +366,7 @@
|
||||
</nav>
|
||||
|
||||
<nav class="bottom s">
|
||||
{#each getPages() as navPage}
|
||||
{#each getPages() as navPage (navPage)}
|
||||
{#if !navPage.requiresAuth || isLoggedIn}
|
||||
<a
|
||||
class="round"
|
||||
@@ -385,7 +390,7 @@
|
||||
{#if notifications.length === 0}
|
||||
<p>{$_('layout.noNewNotifications')}</p>
|
||||
{:else}
|
||||
{#each notifications as notification}
|
||||
{#each notifications as notification (notification)}
|
||||
<article class="no-padding border">
|
||||
<Thumbnail video={notification}></Thumbnail>
|
||||
</article>
|
||||
|
||||
@@ -102,11 +102,11 @@
|
||||
</summary>
|
||||
<article class="scroll medium">
|
||||
<div class="grid">
|
||||
{#each filters as filter}
|
||||
{#each filters as filter (filter)}
|
||||
<div class="s12 m2 l2">
|
||||
<h6>{filter.title}</h6>
|
||||
<ul class="list no-margin no-padding">
|
||||
{#each filter.options as filterOption}
|
||||
{#each filter.options as filterOption (filterOption)}
|
||||
<li>
|
||||
<button
|
||||
class="small border"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { getFeed } from '$lib/api/index';
|
||||
import type { PlaylistPageVideo, Video, VideoBase } from '$lib/api/model';
|
||||
import { feedCacheStore } from '$lib/store';
|
||||
import { _ } from '$lib/i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import ItemsList from '$lib/components/ItemsList.svelte';
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
subscriptions = subscriptions.filter((item) => {
|
||||
return item.authorId !== authorId;
|
||||
});
|
||||
} catch {}
|
||||
} catch {
|
||||
// Continue regradless of error
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export async function load({ url }) {
|
||||
goToUrl.searchParams.set('time', timestamp);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line svelte/no-navigation-without-resolve
|
||||
goto(goToUrl);
|
||||
} else {
|
||||
error(404);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
playlistCacheStore,
|
||||
playlistSettingsStore,
|
||||
syncPartyConnectionsStore,
|
||||
syncPartyPeerStore,
|
||||
type PlayerState
|
||||
} from '$lib/store';
|
||||
import ui from 'beercss';
|
||||
@@ -71,6 +70,7 @@
|
||||
let playerCurrentTime: number = $state(0);
|
||||
|
||||
let premiereTime = $state('');
|
||||
// eslint-disable-next-line no-undef
|
||||
let premiereUpdateInterval: NodeJS.Timeout;
|
||||
|
||||
if (
|
||||
@@ -302,7 +302,7 @@
|
||||
playerElement.ended ||
|
||||
playerElement.currentTime === 0 ||
|
||||
playerElement.readyState <= 2 ||
|
||||
!playerMiniplayerEnabled
|
||||
!$playerMiniplayerEnabled
|
||||
) {
|
||||
playerState.set(undefined);
|
||||
}
|
||||
@@ -363,6 +363,7 @@
|
||||
playertheatreModeIsActive.set(!$playertheatreModeIsActive);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let pauseTimeout: NodeJS.Timeout | undefined = $state();
|
||||
function setPauseTimer() {
|
||||
if (pauseTimeout) {
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
{#if data.content.timestamps.length > 0}
|
||||
<h5 style="margin-bottom: 0;">{$_('player.chapters')}</h5>
|
||||
<div class="grid">
|
||||
{#each data.content.timestamps as timestamp}
|
||||
{#each data.content.timestamps as timestamp (timestamp)}
|
||||
<ContentColumn>
|
||||
<article
|
||||
role="presentation"
|
||||
|
||||
@@ -28,7 +28,9 @@ export async function load({ url }) {
|
||||
if (resolvedUrl.pageType === 'WEB_PAGE_TYPE_CHANNEL') {
|
||||
goto(resolve(`/channel/[authorId]`, { authorId: resolvedUrl.ucid }));
|
||||
}
|
||||
} catch {}
|
||||
} catch {
|
||||
// continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
const defaultPage = get(interfaceDefaultPage);
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
LATEST_VERSION = "1.11.10"
|
||||
LATEST_VERSION = "1.12.0"
|
||||
RELEASE_DATE = datetime.now().strftime("%Y-%-m-%d") # Format: YYYY-M-D
|
||||
|
||||
WORKING_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "materialious")
|
||||
|
||||
Reference in New Issue
Block a user