Svelte 5
This commit is contained in:
Generated
+57
-294
@@ -59,13 +59,13 @@
|
||||
"buffer": "^6.0.3",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.44.1",
|
||||
"eslint-plugin-svelte": "^2.45.1",
|
||||
"i": "^0.3.7",
|
||||
"jsdom": "^25.0.1",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^3.8.6",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^6.0.11"
|
||||
@@ -3891,13 +3891,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz",
|
||||
"integrity": "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
@@ -4289,20 +4282,6 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
@@ -4705,19 +4684,6 @@
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
@@ -4863,16 +4829,6 @@
|
||||
"ieee754": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-crc32": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz",
|
||||
"integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
@@ -5028,41 +4984,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar/node_modules/glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
@@ -6019,16 +5953,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-indent": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
|
||||
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
@@ -8209,19 +8133,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-boolean-object": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
|
||||
@@ -9710,19 +9621,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
@@ -9961,16 +9859,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/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,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
@@ -10991,16 +10879,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz",
|
||||
"integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/redent": {
|
||||
@@ -11730,86 +11619,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sander": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
|
||||
"integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es6-promise": "^3.1.2",
|
||||
"graceful-fs": "^4.1.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "^2.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/sander/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/sander/node_modules/es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sander/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/sander/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/sander/node_modules/rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||
@@ -12200,22 +12009,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/sorcery": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.1.tgz",
|
||||
"integrity": "sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14",
|
||||
"buffer-crc32": "^1.0.0",
|
||||
"minimist": "^1.2.0",
|
||||
"sander": "^0.5.0"
|
||||
},
|
||||
"bin": {
|
||||
"sorcery": "bin/sorcery"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -12597,24 +12390,57 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check": {
|
||||
"version": "3.8.6",
|
||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.8.6.tgz",
|
||||
"integrity": "sha512-ij0u4Lw/sOTREP13BdWZjiXD/BlHE6/e2e34XzmVmsp5IN4kVa3PWP65NM32JAgwjZlwBg/+JtiNV1MM8khu0Q==",
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.1.4.tgz",
|
||||
"integrity": "sha512-v0j7yLbT29MezzaQJPEDwksybTE2Ups9rUxEXy92T06TiA0cbqcO8wAOwNUVkFW6B0hsYHA+oAX3BS8b/2oHtw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"chokidar": "^3.4.1",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"chokidar": "^4.0.1",
|
||||
"fdir": "^6.2.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"sade": "^1.7.4",
|
||||
"svelte-preprocess": "^5.1.3",
|
||||
"typescript": "^5.0.3"
|
||||
"sade": "^1.7.4"
|
||||
},
|
||||
"bin": {
|
||||
"svelte-check": "bin/svelte-check"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0"
|
||||
"svelte": "^4.0.0 || ^5.0.0-next.0",
|
||||
"typescript": ">=5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check/node_modules/fdir": {
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
|
||||
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"picomatch": "^3 || ^4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"picomatch": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-check/node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-eslint-parser": {
|
||||
@@ -12687,69 +12513,6 @@
|
||||
"svelte": "^3.48.0 || ^4 || ^5"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-preprocess": {
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.4.tgz",
|
||||
"integrity": "sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/pug": "^2.0.6",
|
||||
"detect-indent": "^6.1.0",
|
||||
"magic-string": "^0.30.5",
|
||||
"sorcery": "^0.11.0",
|
||||
"strip-indent": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.10.2",
|
||||
"coffeescript": "^2.5.1",
|
||||
"less": "^3.11.3 || ^4.0.0",
|
||||
"postcss": "^7 || ^8",
|
||||
"postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
|
||||
"pug": "^3.0.0",
|
||||
"sass": "^1.26.8",
|
||||
"stylus": "^0.55.0",
|
||||
"sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0",
|
||||
"svelte": "^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0",
|
||||
"typescript": ">=3.9.5 || ^4.0.0 || ^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@babel/core": {
|
||||
"optional": true
|
||||
},
|
||||
"coffeescript": {
|
||||
"optional": true
|
||||
},
|
||||
"less": {
|
||||
"optional": true
|
||||
},
|
||||
"postcss": {
|
||||
"optional": true
|
||||
},
|
||||
"postcss-load-config": {
|
||||
"optional": true
|
||||
},
|
||||
"pug": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"stylus": {
|
||||
"optional": true
|
||||
},
|
||||
"sugarss": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
"buffer": "^6.0.3",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.44.1",
|
||||
"eslint-plugin-svelte": "^2.45.1",
|
||||
"i": "^0.3.7",
|
||||
"jsdom": "^25.0.1",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
"svelte": "^5.19.7",
|
||||
"svelte-check": "^3.8.6",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tslib": "^2.7.0",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^6.0.11"
|
||||
|
||||
@@ -8,9 +8,13 @@
|
||||
import { truncate } from '../misc';
|
||||
import { interfaceLowBandwidthMode } from '../store';
|
||||
|
||||
export let channel: Channel;
|
||||
interface Props {
|
||||
channel: Channel;
|
||||
}
|
||||
|
||||
let channelPfp: HTMLImageElement | undefined;
|
||||
let { channel }: Props = $props();
|
||||
|
||||
let channelPfp: HTMLImageElement | undefined = $state();
|
||||
|
||||
onMount(async () => {
|
||||
if (get(interfaceLowBandwidthMode)) return;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Comment_1 from './Comment.svelte';
|
||||
import { getComments } from '$lib/api';
|
||||
import { type Comment, type Comments } from '$lib/api/model';
|
||||
import { getBestThumbnail, proxyGoogleImage } from '$lib/images';
|
||||
@@ -6,10 +7,14 @@
|
||||
import { numberWithCommas } from '$lib/time';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let comment: Comment;
|
||||
export let videoId: string;
|
||||
interface Props {
|
||||
comment: Comment;
|
||||
videoId: string;
|
||||
}
|
||||
|
||||
let replies: Comments | undefined = undefined;
|
||||
let { comment, videoId }: Props = $props();
|
||||
|
||||
let replies: Comments | undefined = $state(undefined);
|
||||
|
||||
async function loadReplies(continuation: string) {
|
||||
try {
|
||||
@@ -79,20 +84,20 @@
|
||||
|
||||
{#if replies}
|
||||
{#each replies.comments as reply}
|
||||
<svelte:self comment={reply} {videoId} />
|
||||
<Comment_1 comment={reply} {videoId} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if comment.replies && !replies}
|
||||
<button
|
||||
on:click={async () => loadReplies(comment.replies.continuation)}
|
||||
onclick={async () => loadReplies(comment.replies.continuation)}
|
||||
class="transparent replies"
|
||||
>
|
||||
<i class="primary-text">expand_more</i>
|
||||
<span class="primary-text">{comment.replies.replyCount} {$_('replies')}</span>
|
||||
</button>
|
||||
{:else if replies}
|
||||
<button on:click={() => (replies = undefined)} class="transparent replies">
|
||||
<button onclick={() => (replies = undefined)} class="transparent replies">
|
||||
<i class="primary-text">expand_less</i>
|
||||
<span class="primary-text">{$_('hideReplies')}</span>
|
||||
</button>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let largeCol = '2';
|
||||
let { children }: Props = $props();
|
||||
|
||||
let largeCol = $state('2');
|
||||
|
||||
function checkWidth() {
|
||||
if (innerWidth <= 1750) {
|
||||
@@ -19,5 +24,5 @@
|
||||
</script>
|
||||
|
||||
<div class="s12 m6 l{largeCol}">
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
import type { HashTag } from '../api/model';
|
||||
import { truncate } from '../misc';
|
||||
|
||||
export let hashtag: HashTag;
|
||||
interface Props {
|
||||
hashtag: HashTag;
|
||||
}
|
||||
|
||||
let { hashtag }: Props = $props();
|
||||
|
||||
let channelPfp: HTMLImageElement | undefined;
|
||||
</script>
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
import { darkModeStore, themeColorStore } from '../store';
|
||||
import { getDynamicTheme } from '../theme';
|
||||
|
||||
export let classes = '';
|
||||
interface Props {
|
||||
classes?: string;
|
||||
}
|
||||
|
||||
let fillColor = '';
|
||||
let { classes = '' }: Props = $props();
|
||||
|
||||
let fillColor = $state('');
|
||||
|
||||
async function setFill() {
|
||||
fillColor = (await getDynamicTheme())['--primary'];
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { proxyVideoUrl } from '../misc';
|
||||
import { miniPlayerSrcStore, playerProxyVideosStore } from '../store';
|
||||
|
||||
let currentTime: number = 0;
|
||||
let currentTime: number = $state(0);
|
||||
|
||||
function setTime() {
|
||||
const player = (document.getElementById('video') as HTMLVideoElement) || null;
|
||||
@@ -30,7 +30,7 @@
|
||||
{#if $miniPlayerSrcStore && $miniPlayerSrcStore.video.formatStreams.length > 0}
|
||||
<nav class="bottom no-padding">
|
||||
<article class="surface-bright">
|
||||
<button on:click={() => miniPlayerSrcStore.set(null)} class="s circle transparent no-margin">
|
||||
<button onclick={() => miniPlayerSrcStore.set(null)} class="s circle transparent no-margin">
|
||||
<i>close</i>
|
||||
</button>
|
||||
<div class="flex-container">
|
||||
@@ -39,7 +39,7 @@
|
||||
{$miniPlayerSrcStore.video.title}
|
||||
</p>
|
||||
<button
|
||||
on:click={() => miniPlayerSrcStore.set(null)}
|
||||
onclick={() => miniPlayerSrcStore.set(null)}
|
||||
class="m l circle transparent no-margin"
|
||||
>
|
||||
<i>close</i>
|
||||
@@ -49,14 +49,14 @@
|
||||
></progress>
|
||||
</div>
|
||||
<video
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
goto(`/watch/${$miniPlayerSrcStore.video.videoId}?time=${currentTime}`);
|
||||
miniPlayerSrcStore.set(null);
|
||||
}}
|
||||
id="video"
|
||||
style="cursor: pointer;"
|
||||
bind:currentTime
|
||||
on:loadedmetadata={setTime}
|
||||
onloadedmetadata={setTime}
|
||||
controls={false}
|
||||
autoplay
|
||||
src={get(playerProxyVideosStore)
|
||||
|
||||
@@ -41,16 +41,27 @@
|
||||
} from '../store';
|
||||
import { getDynamicTheme, setStatusBarColor } from '../theme';
|
||||
|
||||
export let data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null };
|
||||
export let audioMode = false;
|
||||
export let player: MediaPlayerElement;
|
||||
export let isSyncing: boolean = false;
|
||||
export let isEmbed: boolean = false;
|
||||
export let segments: Segment[] = [];
|
||||
interface Props {
|
||||
data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null };
|
||||
audioMode?: boolean;
|
||||
player: MediaPlayerElement;
|
||||
isSyncing?: boolean;
|
||||
isEmbed?: boolean;
|
||||
segments?: Segment[];
|
||||
}
|
||||
|
||||
let src: PlayerSrc = [];
|
||||
let snackBarAlert = '';
|
||||
let playerIsLive = false;
|
||||
let {
|
||||
data,
|
||||
audioMode = false,
|
||||
player = $bindable(),
|
||||
isSyncing = false,
|
||||
isEmbed = false,
|
||||
segments = $bindable([])
|
||||
}: Props = $props();
|
||||
|
||||
let src: PlayerSrc = $state([]);
|
||||
let snackBarAlert = $state('');
|
||||
let playerIsLive = $state(false);
|
||||
let playerPosSet = false;
|
||||
|
||||
let userVideoSpeed = 1;
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
import { truncate } from '../misc';
|
||||
import { interfaceLowBandwidthMode } from '../store';
|
||||
|
||||
export let playlist: Playlist;
|
||||
export let disabled: boolean = false;
|
||||
interface Props {
|
||||
playlist: Playlist;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
let loading = true;
|
||||
let { playlist, disabled = false }: Props = $props();
|
||||
|
||||
let img: HTMLImageElement;
|
||||
let loading = $state(true);
|
||||
|
||||
let img: HTMLImageElement = $state();
|
||||
|
||||
const playlistLink = `/playlist/${playlist.playlistId}`;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
@@ -12,14 +14,14 @@
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let searchSuggestions = false;
|
||||
let searchSuggestions = $state(false);
|
||||
interfaceSearchSuggestionsStore.subscribe((value) => (searchSuggestions = value));
|
||||
|
||||
let search: string;
|
||||
let suggestionsForSearch: string[] = [];
|
||||
let selectedSuggestionIndex: number = -1;
|
||||
let search: string = $state();
|
||||
let suggestionsForSearch: string[] = $state([]);
|
||||
let selectedSuggestionIndex: number = $state(-1);
|
||||
|
||||
let showSearchBox = false;
|
||||
let showSearchBox = $state(false);
|
||||
|
||||
let debounceTimer: NodeJS.Timeout;
|
||||
function debouncedSearch(event: any) {
|
||||
@@ -97,29 +99,29 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={handleSubmit}>
|
||||
<form onsubmit={preventDefault(handleSubmit)}>
|
||||
<div class="field prefix round fill no-margin search">
|
||||
<i class="front">search</i>
|
||||
<input
|
||||
id="search-box"
|
||||
placeholder={$_('searchPlaceholder')}
|
||||
bind:value={search}
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
showSearchBox = true;
|
||||
}}
|
||||
/>
|
||||
{#if showSearchBox}
|
||||
<menu class="min suggestions-container">
|
||||
<div class="field large prefix suffix no-margin fixed">
|
||||
<i class="front" on:click={() => dispatch('searchCancelled')}>arrow_back</i>
|
||||
<i class="front" onclick={() => dispatch('searchCancelled')}>arrow_back</i>
|
||||
<input
|
||||
placeholder={$_('searchPlaceholder')}
|
||||
type="text"
|
||||
autofocus
|
||||
required
|
||||
bind:value={search}
|
||||
on:keydown={handleKeyDown}
|
||||
on:keyup={(event) => {
|
||||
onkeydown={handleKeyDown}
|
||||
onkeyup={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
handleSubmit();
|
||||
} else {
|
||||
@@ -127,12 +129,12 @@
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<i class="front" on:click={resetSearch}>close</i>
|
||||
<i class="front" onclick={resetSearch}>close</i>
|
||||
</div>
|
||||
{#if searchSuggestions}
|
||||
{#each suggestionsForSearch as suggestion, index}
|
||||
<a
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
search = suggestion;
|
||||
handleSubmit();
|
||||
}}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { ensureNoTrailingSlash } from '../../misc';
|
||||
import { synciousInstanceStore, synciousStore } from '../../store';
|
||||
|
||||
let synciousInstance = get(synciousInstanceStore);
|
||||
let synciousInstance = $state(get(synciousInstanceStore));
|
||||
</script>
|
||||
|
||||
<form
|
||||
on:submit|preventDefault={() =>
|
||||
synciousInstanceStore.set(ensureNoTrailingSlash(synciousInstance))}
|
||||
onsubmit={preventDefault(() =>
|
||||
synciousInstanceStore.set(ensureNoTrailingSlash(synciousInstance)))}
|
||||
>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
@@ -29,7 +31,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$synciousStore}
|
||||
on:click={() => synciousStore.set(!$synciousStore)}
|
||||
onclick={() => synciousStore.set(!$synciousStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { ensureNoTrailingSlash } from '../../misc';
|
||||
@@ -9,11 +11,11 @@
|
||||
deArrowTitlesOnly
|
||||
} from '../../store';
|
||||
|
||||
let deArrowUrl = get(deArrowInstanceStore);
|
||||
let deArrowThumbnailUrl = get(deArrowThumbnailInstanceStore);
|
||||
let deArrowUrl = $state(get(deArrowInstanceStore));
|
||||
let deArrowThumbnailUrl = $state(get(deArrowThumbnailInstanceStore));
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={() => deArrowInstanceStore.set(ensureNoTrailingSlash(deArrowUrl))}>
|
||||
<form onsubmit={preventDefault(() => deArrowInstanceStore.set(ensureNoTrailingSlash(deArrowUrl)))}>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
<input bind:value={deArrowUrl} name="dearrow-instance" type="text" />
|
||||
@@ -25,7 +27,7 @@
|
||||
</nav>
|
||||
</form>
|
||||
|
||||
<form on:submit|preventDefault={() => deArrowThumbnailInstanceStore.set(deArrowThumbnailUrl)}>
|
||||
<form onsubmit={preventDefault(() => deArrowThumbnailInstanceStore.set(deArrowThumbnailUrl))}>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
<input bind:value={deArrowThumbnailUrl} name="dearrow-thumbnail-instance" type="text" />
|
||||
@@ -44,7 +46,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$deArrowTitlesOnly}
|
||||
on:click={() => deArrowTitlesOnly.set(!$deArrowTitlesOnly)}
|
||||
onclick={() => deArrowTitlesOnly.set(!$deArrowTitlesOnly)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
@@ -58,7 +60,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$deArrowEnabledStore}
|
||||
on:click={() => deArrowEnabledStore.set(!$deArrowEnabledStore)}
|
||||
onclick={() => deArrowEnabledStore.set(!$deArrowEnabledStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import { bookmarkletSaveToUrl } from '$lib/externalSettings';
|
||||
import { letterCase, titleCases } from '$lib/letterCasing';
|
||||
@@ -30,10 +32,10 @@
|
||||
themeColorStore
|
||||
} from '../../store';
|
||||
|
||||
let invidiousInstance = get(instanceStore);
|
||||
let region = get(interfaceRegionStore);
|
||||
let forceCase = get(interfaceForceCase);
|
||||
let defaultPage = get(interfaceDefaultPage);
|
||||
let invidiousInstance = $state(get(instanceStore));
|
||||
let region = $state(get(interfaceRegionStore));
|
||||
let forceCase = $state(get(interfaceForceCase));
|
||||
let defaultPage = $state(get(interfaceDefaultPage));
|
||||
|
||||
async function setColor(color: any) {
|
||||
const target = color.target;
|
||||
@@ -58,12 +60,12 @@
|
||||
|
||||
{#if Capacitor.isNativePlatform()}
|
||||
<form
|
||||
on:submit|preventDefault={() => {
|
||||
onsubmit={preventDefault(() => {
|
||||
instanceStore.set(ensureNoTrailingSlash(invidiousInstance));
|
||||
authStore.set(null);
|
||||
goto('/', { replaceState: true });
|
||||
ui('#dialog-settings');
|
||||
}}
|
||||
})}
|
||||
>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
@@ -79,7 +81,7 @@
|
||||
|
||||
<div class="margin"></div>
|
||||
|
||||
<button on:click={toggleDarkMode} class="no-margin">
|
||||
<button onclick={toggleDarkMode} class="no-margin">
|
||||
{#if !$darkModeStore}
|
||||
<i>dark_mode</i>
|
||||
<span>{$_('layout.theme.darkMode')}</span>
|
||||
@@ -91,7 +93,7 @@
|
||||
<button>
|
||||
<i>palette</i>
|
||||
<span>{$_('layout.theme.color')}</span>
|
||||
<input on:change={setColor} type="color" />
|
||||
<input onchange={setColor} type="color" />
|
||||
</button>
|
||||
|
||||
<div class="margin"></div>
|
||||
@@ -106,7 +108,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceAmoledTheme}
|
||||
on:click={() => interfaceAmoledTheme.set(!$interfaceAmoledTheme)}
|
||||
onclick={() => interfaceAmoledTheme.set(!$interfaceAmoledTheme)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -123,7 +125,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceDisplayThumbnailAvatars}
|
||||
on:click={() => interfaceDisplayThumbnailAvatars.set(!$interfaceDisplayThumbnailAvatars)}
|
||||
onclick={() => interfaceDisplayThumbnailAvatars.set(!$interfaceDisplayThumbnailAvatars)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -139,7 +141,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceSearchHistoryEnabled}
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
interfaceSearchHistoryEnabled.set(!$interfaceSearchHistoryEnabled);
|
||||
searchHistoryStore.set([]);
|
||||
}}
|
||||
@@ -158,7 +160,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceLowBandwidthMode}
|
||||
on:click={() => interfaceLowBandwidthMode.set(!$interfaceLowBandwidthMode)}
|
||||
onclick={() => interfaceLowBandwidthMode.set(!$interfaceLowBandwidthMode)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -174,7 +176,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceSearchSuggestionsStore}
|
||||
on:click={() => interfaceSearchSuggestionsStore.set(!$interfaceSearchSuggestionsStore)}
|
||||
onclick={() => interfaceSearchSuggestionsStore.set(!$interfaceSearchSuggestionsStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -190,7 +192,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfacePreviewVideoOnHoverStore}
|
||||
on:click={() => interfacePreviewVideoOnHoverStore.set(!$interfacePreviewVideoOnHoverStore)}
|
||||
onclick={() => interfacePreviewVideoOnHoverStore.set(!$interfacePreviewVideoOnHoverStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -206,7 +208,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceAutoExpandDesc}
|
||||
on:click={() => interfaceAutoExpandDesc.set(!$interfaceAutoExpandDesc)}
|
||||
onclick={() => interfaceAutoExpandDesc.set(!$interfaceAutoExpandDesc)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -222,7 +224,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$interfaceAutoExpandComments}
|
||||
on:click={() => interfaceAutoExpandComments.set(!$interfaceAutoExpandComments)}
|
||||
onclick={() => interfaceAutoExpandComments.set(!$interfaceAutoExpandComments)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -230,7 +232,7 @@
|
||||
</div>
|
||||
|
||||
<div class="field label suffix border">
|
||||
<select name="region" bind:value={region} on:change={() => interfaceRegionStore.set(region)}>
|
||||
<select name="region" bind:value={region} onchange={() => interfaceRegionStore.set(region)}>
|
||||
{#each iso31661 as region}
|
||||
<option selected={$interfaceRegionStore === region.alpha2} value={region.alpha2}
|
||||
>{region.alpha2} - {region.name}</option
|
||||
@@ -242,7 +244,7 @@
|
||||
</div>
|
||||
|
||||
<div class="field label suffix border">
|
||||
<select name="case" bind:value={forceCase} on:change={() => interfaceForceCase.set(forceCase)}>
|
||||
<select name="case" bind:value={forceCase} onchange={() => interfaceForceCase.set(forceCase)}>
|
||||
<option selected={$interfaceForceCase === null} value={null}>Default</option>
|
||||
{#each titleCases as caseType}
|
||||
<option selected={$interfaceForceCase === caseType} value={caseType}
|
||||
@@ -258,7 +260,7 @@
|
||||
<select
|
||||
name="defaultPage"
|
||||
bind:value={defaultPage}
|
||||
on:change={() => interfaceDefaultPage.set(defaultPage)}
|
||||
onchange={() => interfaceDefaultPage.set(defaultPage)}
|
||||
>
|
||||
{#each getPages() as page}
|
||||
{#if !page.requiresAuth || get(authStore)}
|
||||
@@ -276,7 +278,7 @@
|
||||
<h6>{$_('layout.bookmarklet')}</h6>
|
||||
<button
|
||||
class="no-margin"
|
||||
on:click={async () => await Clipboard.write({ string: bookmarkletSaveToUrl() })}
|
||||
onclick={async () => await Clipboard.write({ string: bookmarkletSaveToUrl() })}
|
||||
>{$_('copyUrl')}</button
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
silenceSkipperStore
|
||||
} from '../../store';
|
||||
|
||||
let defaultLanguage = get(playerDefaultLanguage);
|
||||
let defaultLanguage = $state(get(playerDefaultLanguage));
|
||||
|
||||
const languageNames = ISO6391.getAllCodes().map((code) =>
|
||||
ISO6391.getName(code).toLocaleLowerCase()
|
||||
@@ -33,7 +33,7 @@
|
||||
<select
|
||||
name="case"
|
||||
bind:value={defaultLanguage}
|
||||
on:change={() => playerDefaultLanguage.set(defaultLanguage)}
|
||||
onchange={() => playerDefaultLanguage.set(defaultLanguage)}
|
||||
>
|
||||
{#each languageNames as language}
|
||||
<option selected={$playerDefaultLanguage === language} value={language}
|
||||
@@ -54,7 +54,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerMiniPlayerStore}
|
||||
on:click={() => playerMiniPlayerStore.set(!$playerMiniPlayerStore)}
|
||||
onclick={() => playerMiniPlayerStore.set(!$playerMiniPlayerStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -70,7 +70,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerAutoPlayStore}
|
||||
on:click={() => playerAutoPlayStore.set(!$playerAutoPlayStore)}
|
||||
onclick={() => playerAutoPlayStore.set(!$playerAutoPlayStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -86,7 +86,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerAlwaysLoopStore}
|
||||
on:click={() => playerAlwaysLoopStore.set(!$playerAlwaysLoopStore)}
|
||||
onclick={() => playerAlwaysLoopStore.set(!$playerAlwaysLoopStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -103,7 +103,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerAndroidBgPlayer}
|
||||
on:click={() => playerAndroidBgPlayer.set(!$playerAndroidBgPlayer)}
|
||||
onclick={() => playerAndroidBgPlayer.set(!$playerAndroidBgPlayer)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -119,7 +119,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerAndroidLockOrientation}
|
||||
on:click={() => playerAndroidLockOrientation.set(!$playerAndroidLockOrientation)}
|
||||
onclick={() => playerAndroidLockOrientation.set(!$playerAndroidLockOrientation)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -137,7 +137,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerProxyVideosStore}
|
||||
on:click={() => playerProxyVideosStore.set(!$playerProxyVideosStore)}
|
||||
onclick={() => playerProxyVideosStore.set(!$playerProxyVideosStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -154,7 +154,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerSavePlaybackPositionStore}
|
||||
on:click={() => playerSavePlaybackPositionStore.set(!$playerSavePlaybackPositionStore)}
|
||||
onclick={() => playerSavePlaybackPositionStore.set(!$playerSavePlaybackPositionStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -170,7 +170,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerListenByDefaultStore}
|
||||
on:click={() => playerListenByDefaultStore.set(!$playerListenByDefaultStore)}
|
||||
onclick={() => playerListenByDefaultStore.set(!$playerListenByDefaultStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -186,7 +186,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerTheatreModeByDefaultStore}
|
||||
on:click={() => playerTheatreModeByDefaultStore.set(!$playerTheatreModeByDefaultStore)}
|
||||
onclick={() => playerTheatreModeByDefaultStore.set(!$playerTheatreModeByDefaultStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -202,7 +202,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerAutoplayNextByDefaultStore}
|
||||
on:click={() => playerAutoplayNextByDefaultStore.set(!$playerAutoplayNextByDefaultStore)}
|
||||
onclick={() => playerAutoplayNextByDefaultStore.set(!$playerAutoplayNextByDefaultStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -218,7 +218,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$silenceSkipperStore}
|
||||
on:click={() => silenceSkipperStore.set(!$silenceSkipperStore)}
|
||||
onclick={() => silenceSkipperStore.set(!$silenceSkipperStore)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -235,7 +235,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerYouTubeJsAlways}
|
||||
on:click={() => playerYouTubeJsAlways.set(!$playerYouTubeJsAlways)}
|
||||
onclick={() => playerYouTubeJsAlways.set(!$playerYouTubeJsAlways)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
@@ -251,7 +251,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={$playerYouTubeJsFallback}
|
||||
on:click={() => playerYouTubeJsFallback.set(!$playerYouTubeJsFallback)}
|
||||
onclick={() => playerYouTubeJsFallback.set(!$playerYouTubeJsFallback)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { ensureNoTrailingSlash } from '../../misc';
|
||||
import { returnYTDislikesInstanceStore, returnYtDislikesStore } from '../../store';
|
||||
|
||||
let returnYTInstance = get(returnYTDislikesInstanceStore);
|
||||
let returnYTInstance = $state(get(returnYTDislikesInstanceStore));
|
||||
</script>
|
||||
|
||||
<form
|
||||
on:submit|preventDefault={() =>
|
||||
returnYTDislikesInstanceStore.set(ensureNoTrailingSlash(returnYTInstance))}
|
||||
onsubmit={preventDefault(() =>
|
||||
returnYTDislikesInstanceStore.set(ensureNoTrailingSlash(returnYTInstance)))}
|
||||
>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
@@ -29,7 +31,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$returnYtDislikesStore}
|
||||
on:click={() => returnYtDislikesStore.set(!$returnYtDislikesStore)}
|
||||
onclick={() => returnYtDislikesStore.set(!$returnYtDislikesStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
|
||||
@@ -68,9 +68,9 @@
|
||||
| 'ryd'
|
||||
| 'api extended'
|
||||
| 'sponsorblock'
|
||||
| 'dearrow' = 'interface';
|
||||
| 'dearrow' = $state('interface');
|
||||
|
||||
let dialogType = '';
|
||||
let dialogType = $state('');
|
||||
|
||||
function checkWidth() {
|
||||
if (innerWidth <= 1320) {
|
||||
@@ -104,31 +104,31 @@
|
||||
|
||||
<div>
|
||||
<nav class="tabbed small">
|
||||
<a class:active={activeTab === 'interface'} on:click={() => (activeTab = 'interface')}>
|
||||
<a class:active={activeTab === 'interface'} onclick={() => (activeTab = 'interface')}>
|
||||
<i>grid_view</i>
|
||||
<span>{$_('layout.interface')}</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'player'} on:click={() => (activeTab = 'player')}>
|
||||
<a class:active={activeTab === 'player'} onclick={() => (activeTab = 'player')}>
|
||||
<i>smart_display</i>
|
||||
<span>{$_('layout.player.title')}</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'data'} on:click={() => (activeTab = 'data')}>
|
||||
<a class:active={activeTab === 'data'} onclick={() => (activeTab = 'data')}>
|
||||
<i>save</i>
|
||||
<span>{$_('layout.dataPreferences.dataPreferences')}</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'ryd'} on:click={() => (activeTab = 'ryd')}>
|
||||
<a class:active={activeTab === 'ryd'} onclick={() => (activeTab = 'ryd')}>
|
||||
<i>thumb_down</i>
|
||||
<span>RYD</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'api extended'} on:click={() => (activeTab = 'api extended')}>
|
||||
<a class:active={activeTab === 'api extended'} onclick={() => (activeTab = 'api extended')}>
|
||||
<i>sync</i>
|
||||
<span>API Extended</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'sponsorblock'} on:click={() => (activeTab = 'sponsorblock')}>
|
||||
<a class:active={activeTab === 'sponsorblock'} onclick={() => (activeTab = 'sponsorblock')}>
|
||||
<i>block</i>
|
||||
<span>Sponsorblock</span>
|
||||
</a>
|
||||
<a class:active={activeTab === 'dearrow'} on:click={() => (activeTab = 'dearrow')}>
|
||||
<a class:active={activeTab === 'dearrow'} onclick={() => (activeTab = 'dearrow')}>
|
||||
<i>keyboard_double_arrow_down</i>
|
||||
<span>{$_('layout.deArrow.title')}</span>
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { ensureNoTrailingSlash } from '../../misc';
|
||||
@@ -10,10 +12,10 @@
|
||||
sponsorBlockUrlStore
|
||||
} from '../../store';
|
||||
|
||||
let sponsorCategoriesList: string[] = [];
|
||||
let sponsorCategoriesList: string[] = $state([]);
|
||||
sponsorBlockCategoriesStore.subscribe((value) => (sponsorCategoriesList = value));
|
||||
|
||||
let sponsorBlockInstance = get(sponsorBlockUrlStore);
|
||||
let sponsorBlockInstance = $state(get(sponsorBlockUrlStore));
|
||||
|
||||
const sponsorCategories = [
|
||||
{ name: $_('layout.sponsors.sponsor'), category: 'sponsor' },
|
||||
@@ -36,8 +38,8 @@
|
||||
</script>
|
||||
|
||||
<form
|
||||
on:submit|preventDefault={() =>
|
||||
sponsorBlockUrlStore.set(ensureNoTrailingSlash(sponsorBlockInstance))}
|
||||
onsubmit={preventDefault(() =>
|
||||
sponsorBlockUrlStore.set(ensureNoTrailingSlash(sponsorBlockInstance)))}
|
||||
>
|
||||
<nav>
|
||||
<div class="field label border max">
|
||||
@@ -57,7 +59,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$sponsorBlockStore}
|
||||
on:click={() => sponsorBlockStore.set(!$sponsorBlockStore)}
|
||||
onclick={() => sponsorBlockStore.set(!$sponsorBlockStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
@@ -71,7 +73,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$sponsorBlockDisplayToastStore}
|
||||
on:click={() => sponsorBlockDisplayToastStore.set(!$sponsorBlockDisplayToastStore)}
|
||||
onclick={() => sponsorBlockDisplayToastStore.set(!$sponsorBlockDisplayToastStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
@@ -85,7 +87,7 @@
|
||||
<label class="switch">
|
||||
<input
|
||||
bind:checked={$sponsorBlockTimelineStore}
|
||||
on:click={() => sponsorBlockTimelineStore.set(!$sponsorBlockTimelineStore)}
|
||||
onclick={() => sponsorBlockTimelineStore.set(!$sponsorBlockTimelineStore)}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span></span>
|
||||
@@ -106,7 +108,7 @@
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={sponsorCategoriesList.includes(sponsor.category)}
|
||||
on:click={() => toggleSponsor(sponsor.category)}
|
||||
onclick={() => toggleSponsor(sponsor.category)}
|
||||
/>
|
||||
<span></span>
|
||||
</label>
|
||||
|
||||
@@ -4,14 +4,18 @@
|
||||
import { _ } from 'svelte-i18n';
|
||||
import type { Notification, PlaylistPageVideo, Video, VideoBase } from '../api/model';
|
||||
|
||||
export let video: VideoBase | Video | Notification | PlaylistPageVideo;
|
||||
interface Props {
|
||||
video: VideoBase | Video | Notification | PlaylistPageVideo;
|
||||
}
|
||||
|
||||
let { video }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<a
|
||||
class="row"
|
||||
href="#copy"
|
||||
on:click={async () =>
|
||||
onclick={async () =>
|
||||
await Clipboard.write({ string: `${location.origin}/watch/${video.videoId}` })}
|
||||
>
|
||||
<div class="min">{$_('player.share.materialiousLink')}</div></a
|
||||
@@ -20,14 +24,14 @@
|
||||
<a
|
||||
href="#copy"
|
||||
class="row"
|
||||
on:click={async () =>
|
||||
onclick={async () =>
|
||||
await Clipboard.write({ string: `https://redirect.invidious.io/watch?v=${video.videoId}` })}
|
||||
>
|
||||
<div class="min">{$_('player.share.invidiousRedirect')}</div></a
|
||||
><a
|
||||
class="row"
|
||||
href="#copy"
|
||||
on:click={async () =>
|
||||
onclick={async () =>
|
||||
await Clipboard.write({ string: `https://www.youtube.com/watch?v=${video.videoId}` })}
|
||||
>
|
||||
<div class="min">{$_('player.share.youtubeLink')}</div></a
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
<label class="active" for="sync-share">Share URL</label>
|
||||
</div>
|
||||
<button
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: `${location.origin}?sync=${$syncPartyPeerStore?.id}` });
|
||||
}}
|
||||
class="square round"
|
||||
@@ -142,7 +142,7 @@
|
||||
<div class="space"></div>
|
||||
<button
|
||||
class="no-margin"
|
||||
on:click={startWatchSync}
|
||||
onclick={startWatchSync}
|
||||
data-ui={`${$syncPartyPeerStore ? '#sync-party' : ''}`}
|
||||
>{#if $syncPartyPeerStore}
|
||||
{$_('layout.endSyncParty')}
|
||||
|
||||
@@ -26,22 +26,26 @@
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let video: VideoBase | Video | Notification | PlaylistPageVideo;
|
||||
export let playlistId: string = '';
|
||||
export let sideways: boolean = false;
|
||||
interface Props {
|
||||
video: VideoBase | Video | Notification | PlaylistPageVideo;
|
||||
playlistId?: string;
|
||||
sideways?: boolean;
|
||||
}
|
||||
|
||||
let thumbnailHidden: boolean = false;
|
||||
let showVideoPreview: boolean = false;
|
||||
let videoPreview: VideoPlay | null = null;
|
||||
let videoPreviewMuted: boolean = true;
|
||||
let videoPreviewVolume: number = 0.4;
|
||||
let imgHeight: number;
|
||||
let { video = $bindable(), playlistId = '', sideways = $bindable(false) }: Props = $props();
|
||||
|
||||
let authorImg: HTMLImageElement | undefined;
|
||||
let thumbnailHidden: boolean = $state(false);
|
||||
let showVideoPreview: boolean = $state(false);
|
||||
let videoPreview: VideoPlay | null = $state(null);
|
||||
let videoPreviewMuted: boolean = $state(true);
|
||||
let videoPreviewVolume: number = $state(0.4);
|
||||
let imgHeight: number = $state();
|
||||
|
||||
let authorImg: HTMLImageElement | undefined = $state();
|
||||
|
||||
let proxyVideos = get(playerProxyVideosStore);
|
||||
|
||||
let placeholderHeight: number = 0;
|
||||
let placeholderHeight: number = $state(0);
|
||||
|
||||
let watchUrl = new URL(`${location.origin}/watch/${video.videoId}`);
|
||||
|
||||
@@ -55,12 +59,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
let loading = true;
|
||||
let loaded = false;
|
||||
let loading = $state(true);
|
||||
let loaded = $state(false);
|
||||
|
||||
let img: HTMLImageElement;
|
||||
let img: HTMLImageElement = $state();
|
||||
|
||||
let progress: string | null;
|
||||
let progress: string | null = $state();
|
||||
if (get(playerSavePlaybackPositionStore)) {
|
||||
try {
|
||||
progress = localStorage.getItem(`v_${video.videoId}`);
|
||||
@@ -274,9 +278,9 @@
|
||||
{#if !thumbnailHidden}
|
||||
<div class:sideways-root={sideways}>
|
||||
<div
|
||||
on:mouseover={previewVideo}
|
||||
on:mouseleave={() => (showVideoPreview = false)}
|
||||
on:focus={() => {}}
|
||||
onmouseover={previewVideo}
|
||||
onmouseleave={() => (showVideoPreview = false)}
|
||||
onfocus={() => {}}
|
||||
id="thumbnail-container"
|
||||
role="region"
|
||||
>
|
||||
@@ -284,7 +288,7 @@
|
||||
class="wave thumbnail"
|
||||
href={watchUrl.toString()}
|
||||
data-sveltekit-preload-data="off"
|
||||
on:click={syncChangeVideo}
|
||||
onclick={syncChangeVideo}
|
||||
>
|
||||
{#if !$interfaceLowBandwidthMode}
|
||||
{#if loading}
|
||||
@@ -352,7 +356,7 @@
|
||||
<button
|
||||
class="no-padding"
|
||||
style="position: absolute; bottom: 10px; left: 10px; width: 30px; height: 30px;"
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
videoPreviewMuted = !videoPreviewMuted;
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -10,17 +10,21 @@
|
||||
import { decodeHtmlCharCodes } from '../misc';
|
||||
import { instanceStore } from '../store';
|
||||
|
||||
export let video: VideoPlay;
|
||||
export let player: MediaPlayerElement;
|
||||
interface Props {
|
||||
video: VideoPlay;
|
||||
player: MediaPlayerElement;
|
||||
}
|
||||
|
||||
let url: string | null = null;
|
||||
let autoScroll: boolean = true;
|
||||
let { video, player = $bindable() }: Props = $props();
|
||||
|
||||
let transcript: ParsedCaptionsResult | null = null;
|
||||
let transcriptCues: VTTCue[] = [];
|
||||
let isLoading = false;
|
||||
let currentTime = 0;
|
||||
let search: string = '';
|
||||
let url: string | null = $state(null);
|
||||
let autoScroll: boolean = $state(true);
|
||||
|
||||
let transcript: ParsedCaptionsResult | null = $state(null);
|
||||
let transcriptCues: VTTCue[] = $state([]);
|
||||
let isLoading = $state(false);
|
||||
let currentTime = $state(0);
|
||||
let search: string = $state('');
|
||||
|
||||
player.addEventListener('time-update', (event: MediaTimeUpdateEvent) => {
|
||||
currentTime = event.detail.currentTime;
|
||||
@@ -72,7 +76,7 @@
|
||||
<article class="no-elevate" style="position: sticky; top: 0; z-index: 3;">
|
||||
<h6>{$_('transcript')}</h6>
|
||||
<div class="field label suffix border">
|
||||
<select bind:value={url} on:change={loadTranscript} name="captions">
|
||||
<select bind:value={url} onchange={loadTranscript} name="captions">
|
||||
<option selected={true} value={null}>{$_('selectLang')}</option>
|
||||
{#each video.captions as caption}
|
||||
<option value={caption.url}>{caption.label}</option>
|
||||
@@ -85,7 +89,7 @@
|
||||
<div class="max field round suffix prefix small no-margin surface-variant">
|
||||
<i class="front">search</i><input
|
||||
bind:value={search}
|
||||
on:input={searchTranscript}
|
||||
oninput={searchTranscript}
|
||||
type="text"
|
||||
placeholder={$_('searchPlaceholder')}
|
||||
/>
|
||||
@@ -111,7 +115,7 @@
|
||||
<div
|
||||
class="transcript-line"
|
||||
id={`transcript-line-${cue.startTime}`}
|
||||
on:click={() => (player.currentTime = cue.startTime)}
|
||||
onclick={() => (player.currentTime = cue.startTime)}
|
||||
class:secondary-container={currentTime >= cue.startTime && currentTime <= cue.endTime}
|
||||
>
|
||||
<p class="chip no-margin">{videoLength(cue.startTime)}</p>
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
import { authStore } from '../store';
|
||||
import ContentColumn from './ContentColumn.svelte';
|
||||
|
||||
export let videos: VideoBase[] | Video[] | Notification[] | PlaylistPageVideo[] = [];
|
||||
export let playlistId: string = '';
|
||||
export let playlistAuthor: string = '';
|
||||
interface Props {
|
||||
videos?: VideoBase[] | Video[] | Notification[] | PlaylistPageVideo[];
|
||||
playlistId?: string;
|
||||
playlistAuthor?: string;
|
||||
}
|
||||
|
||||
let hiddenVideos: string[] = [];
|
||||
let { videos = [], playlistId = '', playlistAuthor = '' }: Props = $props();
|
||||
|
||||
let hiddenVideos: string[] = $state([]);
|
||||
let auth = get(authStore);
|
||||
|
||||
async function removePlaylistItem(indexId: string, videoId: string) {
|
||||
@@ -36,7 +40,7 @@
|
||||
{#if auth && decodeURIComponent(auth.username) === playlistAuthor && 'indexId' in video}
|
||||
<div class="right-align" style="margin: 1em .5em;">
|
||||
<button
|
||||
on:click={async () => removePlaylistItem(video.indexId, video.videoId)}
|
||||
onclick={async () => removePlaylistItem(video.indexId, video.videoId)}
|
||||
class="tertiary circle small"
|
||||
>
|
||||
<i>delete</i>
|
||||
|
||||
@@ -36,18 +36,23 @@
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { get } from 'svelte/store';
|
||||
import { pwaInfo } from 'virtual:pwa-info';
|
||||
interface Props {
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let mobileSearchShow = false;
|
||||
let { children }: Props = $props();
|
||||
|
||||
let currentPage: string | null = '';
|
||||
let mobileSearchShow = $state(false);
|
||||
|
||||
let currentPage: string | null = $state('');
|
||||
activePageStore.subscribe((page) => (currentPage = page));
|
||||
|
||||
let isLoggedIn = false;
|
||||
let isLoggedIn = $state(false);
|
||||
authStore.subscribe((value) => {
|
||||
isLoggedIn = value !== null;
|
||||
});
|
||||
|
||||
let notifications: Notification[] = [];
|
||||
let notifications: Notification[] = $state([]);
|
||||
|
||||
interfaceAmoledTheme.subscribe(async () => {
|
||||
setAmoledTheme();
|
||||
@@ -178,7 +183,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
$: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : '';
|
||||
let webManifestLink = $derived(pwaInfo ? pwaInfo.webManifest.linkTag : '');
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -200,7 +205,7 @@
|
||||
<nav class="top">
|
||||
{#if !mobileSearchShow}
|
||||
<button
|
||||
on:click={() => (mobileSearchShow = !mobileSearchShow)}
|
||||
onclick={() => (mobileSearchShow = !mobileSearchShow)}
|
||||
class="transparent s circle large"
|
||||
>
|
||||
<i>search</i>
|
||||
@@ -209,16 +214,16 @@
|
||||
|
||||
{#if Capacitor.getPlatform() === 'electron'}
|
||||
<nav class="no-space">
|
||||
<button on:click={() => window.history.back()} class="border left-round">
|
||||
<button onclick={() => window.history.back()} class="border left-round">
|
||||
<i>arrow_back</i>
|
||||
</button>
|
||||
<button on:click={() => window.history.forward()} class="border right-round">
|
||||
<button onclick={() => window.history.forward()} class="border right-round">
|
||||
<i>arrow_forward</i>
|
||||
</button>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
<nav on:click={() => goto('/')} style="cursor: pointer;" class="m l">
|
||||
<nav onclick={() => goto('/')} style="cursor: pointer;" class="m l">
|
||||
<Logo />
|
||||
<h6 class="l">Materialious</h6>
|
||||
</nav>
|
||||
@@ -243,23 +248,23 @@
|
||||
</button>
|
||||
{/if}
|
||||
{#if isLoggedIn}
|
||||
<button class="circle large transparent" on:click={() => ui('#dialog-notifications')}
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-notifications')}
|
||||
><i>notifications</i>
|
||||
<div class="tooltip bottom">{$_('layout.notifications')}</div>
|
||||
</button>
|
||||
{/if}
|
||||
<button class="circle large transparent" on:click={() => ui('#dialog-settings')}>
|
||||
<button class="circle large transparent" onclick={() => ui('#dialog-settings')}>
|
||||
<i>settings</i>
|
||||
<div class="tooltip bottom">{$_('layout.settings')}</div>
|
||||
</button>
|
||||
|
||||
{#if !isLoggedIn}
|
||||
<button on:click={login} class="circle large transparent">
|
||||
<button onclick={login} class="circle large transparent">
|
||||
<i>login</i>
|
||||
<div class="tooltip bottom">{$_('layout.login')}</div>
|
||||
</button>
|
||||
{:else}
|
||||
<button on:click={logout} class="circle large transparent">
|
||||
<button onclick={logout} class="circle large transparent">
|
||||
<i>logout</i>
|
||||
<div class="tooltip bottom">{$_('layout.logout')}</div>
|
||||
</button>
|
||||
@@ -315,7 +320,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<nav class="right-align no-space">
|
||||
<button class="transparent link" on:click={() => showWarningStore.set(false)}
|
||||
<button class="transparent link" onclick={() => showWarningStore.set(false)}
|
||||
>Don't show again</button
|
||||
>
|
||||
</nav>
|
||||
@@ -324,7 +329,7 @@
|
||||
{#if $navigating}
|
||||
<PageLoading />
|
||||
{:else}
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
|
||||
<SyncParty />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import VideoList from '$lib/components/VideoList.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
activePageStore.set('home');
|
||||
</script>
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
activePageStore.set(null);
|
||||
|
||||
let isSubscribed = false;
|
||||
let isSubscribed = $state(false);
|
||||
|
||||
let tab: 'videos' | 'playlists' | 'streams' | 'shorts' = 'videos';
|
||||
let tab: 'videos' | 'playlists' | 'streams' | 'shorts' = $state('videos');
|
||||
|
||||
let displayContent: ChannelContentPlaylists | ChannelContentVideos | undefined = undefined;
|
||||
let displayContent: ChannelContentPlaylists | ChannelContentVideos | undefined = $state(undefined);
|
||||
|
||||
async function loadMore(event: InfiniteEvent) {
|
||||
if (typeof displayContent === 'undefined') return;
|
||||
@@ -61,7 +61,7 @@
|
||||
displayContent = await getChannelContent(data.channel.authorId, { type: tab });
|
||||
}
|
||||
|
||||
let channelPfp: string;
|
||||
let channelPfp: string = $state();
|
||||
onMount(async () => {
|
||||
displayContent = await getChannelContent(data.channel.authorId, { type: 'videos' });
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<div class="grid no-padding">
|
||||
<div class="s12 m12 l5">
|
||||
<button
|
||||
on:click={toggleSubscribed}
|
||||
onclick={toggleSubscribed}
|
||||
class:inverse-surface={!isSubscribed}
|
||||
class:border={isSubscribed}
|
||||
>
|
||||
@@ -138,14 +138,14 @@
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<a
|
||||
href="#share"
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
}}>{$_('player.share.materialiousLink')}</a
|
||||
>
|
||||
{/if}
|
||||
<a
|
||||
href="#share"
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/channel/${data.channel.authorId}`
|
||||
});
|
||||
@@ -159,19 +159,19 @@
|
||||
|
||||
<div class="tabs left-align scroll">
|
||||
{#if data.channel.tabs.includes('videos')}
|
||||
<a class:active={tab === 'videos'} on:click={() => changeTab('videos')} href={`#video`}>
|
||||
<a class:active={tab === 'videos'} onclick={() => changeTab('videos')} href={`#video`}>
|
||||
<i>movie</i>
|
||||
<span>{$_('videoTabs.videos')}</span>
|
||||
</a>
|
||||
{/if}
|
||||
{#if data.channel.tabs.includes('shorts')}
|
||||
<a class:active={tab === 'shorts'} on:click={() => changeTab('shorts')} href={`#short`}>
|
||||
<a class:active={tab === 'shorts'} onclick={() => changeTab('shorts')} href={`#short`}>
|
||||
<i>smartphone</i>
|
||||
<span>{$_('videoTabs.shorts')}</span>
|
||||
</a>
|
||||
{/if}
|
||||
{#if data.channel.tabs.includes('streams')}
|
||||
<a class:active={tab === 'streams'} on:click={() => changeTab('streams')} href={`#stream`}>
|
||||
<a class:active={tab === 'streams'} onclick={() => changeTab('streams')} href={`#stream`}>
|
||||
<i>stream</i>
|
||||
<span>{$_('videoTabs.streams')}</span>
|
||||
</a>
|
||||
@@ -179,7 +179,7 @@
|
||||
{#if data.channel.tabs.includes('playlists')}
|
||||
<a
|
||||
class:active={tab === 'playlists'}
|
||||
on:click={() => changeTab('playlists')}
|
||||
onclick={() => changeTab('playlists')}
|
||||
href={`#playlist`}
|
||||
>
|
||||
<i>playlist_add_check</i>
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { getHashtag } from '$lib/api';
|
||||
import VideoList from '$lib/components/VideoList.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
let currentPage = 1;
|
||||
$: videos = [...data.hashTagVideos.results];
|
||||
let videos;
|
||||
run(() => {
|
||||
videos = [...data.hashTagVideos.results];
|
||||
});
|
||||
|
||||
activePageStore.set('hashtag');
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
activePageStore.set('history');
|
||||
|
||||
let history: VideoPlay[] = [];
|
||||
let loaded = false;
|
||||
let history: VideoPlay[] = $state([]);
|
||||
let loaded = $state(false);
|
||||
|
||||
let currentPage = 1;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="space"></div>
|
||||
<nav class="right-align">
|
||||
<button
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await deleteHistory();
|
||||
|
||||
if (get(synciousStore)) {
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
activePageStore.set(null);
|
||||
|
||||
let videos: PlaylistPageVideo[] | undefined;
|
||||
let videos: PlaylistPageVideo[] | undefined = $state();
|
||||
if (data.playlist.videos.length > 0) {
|
||||
videos = data.playlist.videos.sort((a: PlaylistPageVideo, b: PlaylistPageVideo) => {
|
||||
return a.index < b.index ? -1 : 1;
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<a
|
||||
href={`/watch/${unsafeRandomItem(videos).videoId}?playlist=${data.playlist.playlistId}`}
|
||||
on:click={() =>
|
||||
onclick={() =>
|
||||
playlistSettingsStore.set({ [data.playlist.playlistId]: { shuffle: true, loop: false } })}
|
||||
class="button circle extra no-margin border"
|
||||
>
|
||||
@@ -91,14 +91,14 @@
|
||||
{#if !Capacitor.isNativePlatform()}
|
||||
<a
|
||||
href="#share"
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await Clipboard.write({ string: location.href });
|
||||
}}>{$_('player.share.materialiousLink')}</a
|
||||
>
|
||||
{/if}
|
||||
<a
|
||||
href="#share"
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
await Clipboard.write({
|
||||
string: `https://www.youtube.com/playlist?list=${data.playlist.playlistId}`
|
||||
});
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { preventDefault } from 'svelte/legacy';
|
||||
|
||||
import { deletePersonalPlaylist, getPersonalPlaylists, postPersonalPlaylist } from '$lib/api';
|
||||
import ContentColumn from '$lib/components/ContentColumn.svelte';
|
||||
import PlaylistThumbnail from '$lib/components/PlaylistThumbnail.svelte';
|
||||
@@ -6,12 +8,12 @@
|
||||
import { ui } from 'beercss';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let data;
|
||||
let { data = $bindable() } = $props();
|
||||
|
||||
activePageStore.set('playlists');
|
||||
|
||||
let playlistPrivacy: 'public' | 'private' | 'unlisted' = 'public';
|
||||
let playlistTitle: string;
|
||||
let playlistTitle: string = $state();
|
||||
|
||||
function onPrivacyChange(event: any) {
|
||||
playlistPrivacy = event.currentTarget.value;
|
||||
@@ -43,7 +45,7 @@
|
||||
|
||||
<nav class="right-align padding">
|
||||
<button
|
||||
on:click={async () => await removePlaylistItem(playlist.playlistId)}
|
||||
onclick={async () => await removePlaylistItem(playlist.playlistId)}
|
||||
class="tertiary square round"
|
||||
>
|
||||
<i>delete</i>
|
||||
@@ -54,7 +56,7 @@
|
||||
{/each}
|
||||
<ContentColumn>
|
||||
<article style="height: 100%;display: flex;align-items: center;justify-content: center;">
|
||||
<button on:click={() => ui('#create-playlist')} class="round extra">
|
||||
<button onclick={() => ui('#create-playlist')} class="round extra">
|
||||
<i>add_circle</i>
|
||||
<span>{$_('playlist.createPlaylist')}</span>
|
||||
</button>
|
||||
@@ -64,7 +66,7 @@
|
||||
</div>
|
||||
|
||||
<dialog id="create-playlist">
|
||||
<form on:submit|preventDefault={createPlaylist}>
|
||||
<form onsubmit={preventDefault(createPlaylist)}>
|
||||
<div class="field label border">
|
||||
<input bind:value={playlistTitle} required name="title" type="text" />
|
||||
<label for="title">{$_('title')}</label>
|
||||
@@ -72,21 +74,21 @@
|
||||
<div class="field middle-align">
|
||||
<nav>
|
||||
<label class="radio">
|
||||
<input checked on:change={onPrivacyChange} value="public" type="radio" name="privacy" />
|
||||
<input checked onchange={onPrivacyChange} value="public" type="radio" name="privacy" />
|
||||
<span>{$_('playlist.public')}</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input on:change={onPrivacyChange} type="radio" value="unlisted" name="privacy" />
|
||||
<input onchange={onPrivacyChange} type="radio" value="unlisted" name="privacy" />
|
||||
<span>{$_('playlist.unlisted')}</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input on:change={onPrivacyChange} type="radio" value="private" name="privacy" />
|
||||
<input onchange={onPrivacyChange} type="radio" value="private" name="privacy" />
|
||||
<span>{$_('playlist.private')}</span>
|
||||
</label>
|
||||
</nav>
|
||||
</div>
|
||||
<nav class="right-align">
|
||||
<button type="button" on:click={() => ui('#create-playlist')}>{$_('cancel')}</button>
|
||||
<button type="button" onclick={() => ui('#create-playlist')}>{$_('cancel')}</button>
|
||||
<button type="submit">{$_('create')}</button>
|
||||
</nav>
|
||||
</form>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
|
||||
export let data;
|
||||
let { data = $bindable() } = $props();
|
||||
|
||||
let currentPage = 1;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<a
|
||||
class:active={data.searchType === 'all'}
|
||||
href="#all"
|
||||
on:click={async () => changeType('all')}
|
||||
onclick={async () => changeType('all')}
|
||||
>
|
||||
<i>home</i>
|
||||
<span>{$_('videoTabs.all')}</span>
|
||||
@@ -52,7 +52,7 @@
|
||||
<a
|
||||
class:active={data.searchType === 'video'}
|
||||
href="#videos"
|
||||
on:click={async () => changeType('video')}
|
||||
onclick={async () => changeType('video')}
|
||||
>
|
||||
<i>movie</i>
|
||||
<span>{$_('videoTabs.videos')}</span>
|
||||
@@ -60,7 +60,7 @@
|
||||
<a
|
||||
class:active={data.searchType === 'playlist'}
|
||||
href="#playlists"
|
||||
on:click={async () => changeType('playlist')}
|
||||
onclick={async () => changeType('playlist')}
|
||||
>
|
||||
<i>playlist_add_check</i>
|
||||
<span>{$_('videoTabs.playlists')}</span>
|
||||
@@ -68,7 +68,7 @@
|
||||
<a
|
||||
class:active={data.searchType === 'channel'}
|
||||
href="#channels"
|
||||
on:click={async () => changeType('channel')}
|
||||
onclick={async () => changeType('channel')}
|
||||
>
|
||||
<i>person</i>
|
||||
<span>{$_('videoTabs.channels')}</span>
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { getFeed } from '$lib/api/index';
|
||||
import VideoList from '$lib/components/VideoList.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
let currentPage = 1;
|
||||
$: videos = [...data.feed.notifications, ...data.feed.videos];
|
||||
let videos;
|
||||
run(() => {
|
||||
videos = [...data.feed.notifications, ...data.feed.videos];
|
||||
});
|
||||
|
||||
activePageStore.set('subscriptions');
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
activePageStore.set(null);
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
let subscriptions = structuredClone(data.subscriptions);
|
||||
let subscriptions = $state(structuredClone(data.subscriptions));
|
||||
|
||||
let search: string;
|
||||
let search: string = $state();
|
||||
|
||||
const fuse = new Fuse(subscriptions, {
|
||||
keys: ['author']
|
||||
@@ -39,7 +39,7 @@
|
||||
<div class="max field round suffix prefix small no-margin surface-variant">
|
||||
<i class="front">search</i><input
|
||||
bind:value={search}
|
||||
on:input={searchSubs}
|
||||
oninput={searchSubs}
|
||||
type="text"
|
||||
placeholder={$_('searchPlaceholder')}
|
||||
/>
|
||||
@@ -54,7 +54,7 @@
|
||||
</h6></a
|
||||
>
|
||||
<div class="max"></div>
|
||||
<button on:click={async () => unsubscribe(sub.authorId)} class="border">Unsubscribe</button>
|
||||
<button onclick={async () => unsubscribe(sub.authorId)} class="border">Unsubscribe</button>
|
||||
</nav>
|
||||
</article>
|
||||
{/each}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import VideoList from '$lib/components/VideoList.svelte';
|
||||
import { activePageStore } from '$lib/store';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
activePageStore.set('trending');
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import {
|
||||
addPlaylistVideo,
|
||||
@@ -44,49 +46,51 @@
|
||||
import type { MediaTimeUpdateEvent } from 'vidstack';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
|
||||
export let data;
|
||||
let { data = $bindable() } = $props();
|
||||
|
||||
let comments: Comments | null = null;
|
||||
let comments: Comments | null = $state(null);
|
||||
data.streamed.comments?.then((streamedComments) => {
|
||||
comments = streamedComments;
|
||||
});
|
||||
|
||||
let subscribed: boolean = false;
|
||||
let subscribed: boolean = $state(false);
|
||||
data.streamed.subscribed.then((streamedIsSubbed) => {
|
||||
subscribed = streamedIsSubbed;
|
||||
});
|
||||
|
||||
let personalPlaylists: PlaylistPage[] | null = null;
|
||||
let personalPlaylists: PlaylistPage[] | null = $state(null);
|
||||
data.streamed.personalPlaylists?.then((streamPlaylists) => (personalPlaylists = streamPlaylists));
|
||||
|
||||
activePageStore.set(null);
|
||||
|
||||
let playlistVideos: PlaylistPageVideo[] = [];
|
||||
let playlist: PlaylistPage | null = null;
|
||||
let playlistVideos: PlaylistPageVideo[] = $state([]);
|
||||
let playlist: PlaylistPage | null = $state(null);
|
||||
|
||||
let loopPlaylist: boolean = false;
|
||||
let shufflePlaylist: boolean = false;
|
||||
let loopPlaylist: boolean = $state(false);
|
||||
let shufflePlaylist: boolean = $state(false);
|
||||
|
||||
let theatreMode = get(playerTheatreModeByDefaultStore);
|
||||
let theatreMode = $state(get(playerTheatreModeByDefaultStore));
|
||||
|
||||
let audioMode = get(playerListenByDefaultStore);
|
||||
let player: MediaPlayerElement;
|
||||
let audioMode = $state(get(playerListenByDefaultStore));
|
||||
let player: MediaPlayerElement = $state();
|
||||
|
||||
let segments: Segment[] = [];
|
||||
let segments: Segment[] = $state([]);
|
||||
|
||||
let pauseTimerSeconds: number = -1;
|
||||
let pauseTimerSeconds: number = $state(-1);
|
||||
|
||||
let showTranscript = false;
|
||||
let showTranscript = $state(false);
|
||||
|
||||
let playerCurrentTime: number = 0;
|
||||
let playerCurrentTime: number = $state(0);
|
||||
// @ts-ignore
|
||||
$: if (typeof player !== 'undefined') {
|
||||
playerCurrentTime = player.currentTime;
|
||||
player.addEventListener(
|
||||
'time-update',
|
||||
(event: MediaTimeUpdateEvent) => (playerCurrentTime = event.detail.currentTime)
|
||||
);
|
||||
}
|
||||
run(() => {
|
||||
if (typeof player !== 'undefined') {
|
||||
playerCurrentTime = player.currentTime;
|
||||
player.addEventListener(
|
||||
'time-update',
|
||||
(event: MediaTimeUpdateEvent) => (playerCurrentTime = event.detail.currentTime)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
playlistSettingsStore.subscribe((playlistSetting) => {
|
||||
if (!data.playlistId) return;
|
||||
@@ -411,7 +415,7 @@
|
||||
theatreMode = !theatreMode;
|
||||
}
|
||||
|
||||
let pauseTimeout: NodeJS.Timeout;
|
||||
let pauseTimeout: NodeJS.Timeout = $state();
|
||||
function setPauseTimer() {
|
||||
if (pauseTimeout) {
|
||||
clearTimeout(pauseTimeout);
|
||||
@@ -487,7 +491,7 @@
|
||||
</a>
|
||||
{#if $authStore}
|
||||
<button
|
||||
on:click={toggleSubscribed}
|
||||
onclick={toggleSubscribed}
|
||||
class:inverse-surface={!subscribed}
|
||||
class:border={subscribed}
|
||||
>
|
||||
@@ -529,17 +533,17 @@
|
||||
{/await}
|
||||
|
||||
<div>
|
||||
<button on:click={() => (audioMode = !audioMode)} class:border={!audioMode}>
|
||||
<button onclick={() => (audioMode = !audioMode)} class:border={!audioMode}>
|
||||
<i>headphones</i>
|
||||
<div class="tooltip">{$_('player.audioOnly')}</div>
|
||||
</button>
|
||||
<button on:click={toggleTheatreMode} class="m l" class:border={!theatreMode}>
|
||||
<button onclick={toggleTheatreMode} class="m l" class:border={!theatreMode}>
|
||||
<i>width_wide</i>
|
||||
<div class="tooltip">{$_('player.theatreMode')}</div>
|
||||
</button>
|
||||
{#if data.video.lengthSeconds > 60 && !data.video.hlsUrl}
|
||||
<button
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (pauseTimeout) {
|
||||
clearTimeout(pauseTimeout);
|
||||
}
|
||||
@@ -553,7 +557,7 @@
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
on:click={() => ((showTranscript = !showTranscript), (theatreMode = false))}
|
||||
onclick={() => ((showTranscript = !showTranscript), (theatreMode = false))}
|
||||
class:border={!showTranscript}
|
||||
>
|
||||
<i>description</i>
|
||||
@@ -578,7 +582,7 @@
|
||||
{#each personalPlaylists as personalPlaylist}
|
||||
<a
|
||||
href="#add"
|
||||
on:click={async () => await toggleVideoToPlaylist(personalPlaylist.playlistId)}
|
||||
onclick={async () => await toggleVideoToPlaylist(personalPlaylist.playlistId)}
|
||||
>
|
||||
<nav>
|
||||
<span class="max">{personalPlaylist.title}</span>
|
||||
@@ -629,7 +633,7 @@
|
||||
{#if data.content.timestamps.length > 0}
|
||||
<h6 style="margin-bottom: .3em;">Chapters</h6>
|
||||
{#each data.content.timestamps as timestamp}
|
||||
<button on:click={() => (player.currentTime = timestamp.time)} class="timestamps"
|
||||
<button onclick={() => (player.currentTime = timestamp.time)} class="timestamps"
|
||||
>{timestamp.timePretty}
|
||||
{#if !timestamp.title.startsWith('-')}
|
||||
-
|
||||
@@ -668,7 +672,7 @@
|
||||
<Comment {comment} videoId={data.video.videoId}></Comment>
|
||||
{/each}
|
||||
{#if comments.continuation}
|
||||
<button on:click={loadMoreComments} class="margin">{$_('loadMore')}</button>
|
||||
<button onclick={loadMoreComments} class="margin">{$_('loadMore')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</details>
|
||||
@@ -696,7 +700,7 @@
|
||||
<p><a href={`/channel/${playlist.authorId}`}>{playlist.author}</a></p>
|
||||
<nav>
|
||||
<button
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (!playlist) return;
|
||||
|
||||
loopPlaylist = !loopPlaylist;
|
||||
@@ -713,7 +717,7 @@
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (!playlist) return;
|
||||
|
||||
shufflePlaylist = !shufflePlaylist;
|
||||
@@ -788,12 +792,12 @@
|
||||
<nav class="right-align no-space">
|
||||
<button
|
||||
class="transparent link"
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
ui('#pause-timer');
|
||||
pauseTimerSeconds = 0;
|
||||
}}>Cancel</button
|
||||
>
|
||||
<button disabled={pauseTimerSeconds < 1} class="transparent link" on:click={setPauseTimer}
|
||||
<button disabled={pauseTimerSeconds < 1} class="transparent link" onclick={setPauseTimer}
|
||||
>Confirm</button
|
||||
>
|
||||
</nav>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import Player from '$lib/components/Player.svelte';
|
||||
import type { MediaPlayerElement } from 'vidstack/elements';
|
||||
|
||||
export let data;
|
||||
let { data } = $props();
|
||||
|
||||
let player: MediaPlayerElement;
|
||||
let player: MediaPlayerElement = $state();
|
||||
</script>
|
||||
|
||||
<Player bind:player isEmbed={true} {data} />
|
||||
|
||||
Reference in New Issue
Block a user